/**
   @file sys_usw_acl_api.c

   @date 2015-11-01

   @version v3.0

 */

/****************************************************************************
*
* Header Files
*
****************************************************************************/
#include "drv_api.h"
#include "dal.h"

#include "ctc_error.h"
#include "ctc_const.h"
#include "ctc_common.h"
#include "ctc_macro.h"
#include "ctc_debug.h"
#include "ctc_hash.h"
#include "ctc_parser.h"
#include "ctc_acl.h"
#include "ctc_linklist.h"
#include "ctc_spool.h"
#include "ctc_field.h"
#include "ctc_packet.h"

#include "sys_usw_common.h"
#include "sys_usw_opf.h"
#include "sys_usw_chip.h"
#include "sys_usw_parser.h"
#include "sys_usw_parser_io.h"
#include "sys_usw_ftm.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_register.h"
#include "sys_usw_port_api.h"
#include "sys_usw_acl.h"
#include "sys_usw_scl_api.h"
#include "sys_usw_dma.h"
enum sys_acl_udf_pos_type_e
{
    SYS_ACL_UDF_POSTYPE_NONE,
    SYS_ACL_UDF_POSTYPE_OUTER_L2,
    SYS_ACL_UDF_POSTYPE_OUTER_L3,
    SYS_ACL_UDF_POSTYPE_OUTER_L4,
    SYS_ACL_UDF_POSTYPE_INNER_L2,
    SYS_ACL_UDF_POSTYPE_INNER_L3,
    SYS_ACL_UDF_POSTYPE_INNER_L4,
    SYS_ACL_UDF_POSTYPE_RSV,
    MAX_SYS_ACL_UDF_POSTYPE
};
typedef enum sys_acl_udf_pos_type_e sys_acl_udf_pos_type_t;
extern int32
sys_usw_acl_check_entry_type(uint8 lchip, uint32 group_id, sys_acl_group_t* pg, ctc_acl_entry_t* p_ctc_entry);

extern sys_acl_master_t* p_usw_acl_master[CTC_MAX_LOCAL_CHIP_NUM_PP];
extern dal_op_t g_dal_op;

#define SYS_ACL_FK_TYPE_VALID_CHECK(key_type)   \
    if (!SYS_ACL_KEY_IS_RSVD(key_type) && (key_type < CTC_ACL_KEY_FLEX_BASE)) CTC_ERROR_RETURN(CTC_E_INVALID_PARAM)
#define SYS_ACL_MAX_TCAM_IDX_NUM  16*1024
#define SYS_UDF_AD_VEC_BLK_SIZE   16
#define SYS_ACL_LDP_HASH_NUM 2048

#define _ACL_OTHER
int32
sys_usw_acl_set_global_cfg(uint8 lchip, uint8 property, uint32 value)
{
    sys_acl_register_t acl_register;
    SYS_ACL_INIT_CHECK();

    sal_memset(&acl_register, 0, sizeof(acl_register));
    if (SYS_ACL_XGPON_GEM_PORT_EN == property)
    {
        acl_register.xgpon_gem_port_en = value;
    }
    else if(SYS_ACL_HASH_HALF_AD_EN == property)
    {
        uint32 entry_num = 0;
        sys_usw_opf_t opf;
        uint32 tbl_id = value ? DsFlowHalf_t : DsFlow_t;
        if(p_usw_acl_master[lchip]->key_count[ACL_ALLOC_COUNT_HASH])
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Must remove all acl hash entry befor enable half ad mode\n");
            return CTC_E_INVALID_PARAM;
        }

        /*hash-ad opf*/
        sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
        entry_num = 0;
        if(p_usw_acl_master[lchip]->opf_type_ad)
        {
            sys_usw_opf_deinit(lchip, p_usw_acl_master[lchip]->opf_type_ad);
            p_usw_acl_master[lchip]->opf_type_ad = 0;
        }
        CTC_ERROR_RETURN(sys_usw_ftm_query_table_entry_num(lchip, tbl_id, &entry_num));
        if (entry_num)
        {
            CTC_ERROR_RETURN(sys_usw_opf_init(lchip, &p_usw_acl_master[lchip]->opf_type_ad, 1, "opf-acl-ad"));

            opf.pool_index = 0;
            opf.pool_type  = p_usw_acl_master[lchip]->opf_type_ad;
            CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 0, entry_num));
        }

    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_ERROR_RETURN(_sys_usw_acl_set_register(lchip, &acl_register));
    return CTC_E_NONE;
}

int32
sys_usw_acl_set_ifa_ver(uint8 lchip, uint8 ifa_ver)
{
    SYS_ACL_INIT_CHECK();

    SYS_USW_ACL_LOCK(lchip);
    p_usw_acl_master[SYS_PP_BASE(lchip)]->ifa_ver = ifa_ver;
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

#if 0
int32 sys_usw_acl_vlan_tag_op_untranslate(uint8 lchip, uint8 op_in, uint8 mo_in, uint8* op_out)
{
    if(mo_in && (op_in==1))
    {
        *op_out = CTC_VLAN_TAG_OP_REP_OR_ADD;
        return CTC_E_NONE;
    }

    switch(op_in)
    {
        case 0:
            *op_out = CTC_VLAN_TAG_OP_NONE;
            break;
        case 1:
            *op_out = CTC_VLAN_TAG_OP_REP;
            break;
        case 2:
            *op_out = CTC_VLAN_TAG_OP_ADD;
            break;
        case 3:
            *op_out = CTC_VLAN_TAG_OP_DEL;
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}
#endif

#define _ACL_FLEX_KEY_

STATIC int32
_sys_usw_acl_set_key_fields(uint8 lchip, ctc_acl_flex_key_t* acl_flex_key)
{
    uint8  service_queue_egress_en = 0;
    uint8  support_vsi_check = 0;
    uint8  key_port_mode_check = 0;
    uint8  mac_l3_ext_key_mac_sa_mode = 0;
    uint8  mac_l3_key_mac_sa_mode = 0;
    uint8  mac_l3_key_mac_da_mode = 0;
    uint8  copp_key_basic_mac_da_mode = 0;
    uint8  mac_l3_ext_key_mac_da_mode = 0;
    uint8  cid_key_v6_use_ipda = 0;
    uint8  copp_key_use_ctag = 0;
    uint8  copp_key_use_l3l4_type = 0;
    uint8  copp_key_use_udf = 0;
    uint8  copp_basic_key_ipaddr_use_ipsa = 0;
    uint8  copp_ext_key_ipv6sa = 0;
    uint8  copp_ext_key_use_udf = 0;
    uint8  short_key_use_svlan = 0;
    uint8  l2type_use_vlanNum = 0;
    uint8  key_mergedata_mode = 0;
    uint8  arware_tunnel_info = 0;
    uint8  macl3basic_key_cvlan_mode = 0;
    uint8  copp_key = 0;
    uint8  vlan_mode = 0;
    uint8  key_l4_port_mode = 0;
    uint8  kset_is_empty = FALSE;
    uint32 loop = 0;
    uint32 cmd = 0;
    uint32 xgpon_use_gem_port = 0;
    sys_acl_kset_t* p_kset_base = NULL;
    ctc_acl_kset_t* p_kset_user = NULL;
    sys_acl_fixed_key_t* p_fixed_key = NULL;
    sys_acl_group_t pg;
    ctc_acl_entry_t ctc_entry;
    FlowTcamLookupCtl_m flow_ctl;
    IpePreLookupAclCtl_m ipe_pre_lkup_ctl;
    EpePktProcCtl_m      epe_pkt_proc_ctl;

    kset_is_empty = sys_usw_acl_array_is_empty((uint8*)acl_flex_key->kset.w, CTC_B2W_SIZE(CTC_FIELD_KEY_NUM)*sizeof(uint32));
    p_fixed_key = ctc_vector_get(p_usw_acl_master[lchip]->fixed_key_vec, acl_flex_key->key_type);
    if (!kset_is_empty && NULL != p_fixed_key)
    {   /*update*/
        return CTC_E_EXIST;
    }
    else if (kset_is_empty && NULL == p_fixed_key)
    {   /*do nothing*/
        return CTC_E_NONE;
    }
    else if (kset_is_empty && NULL != p_fixed_key)
    {   /*unset*/
        if (p_fixed_key->entry_count)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Flex key is in use, entry_count:%u!\n", p_fixed_key->entry_count);
            return CTC_E_INVALID_CONFIG;
        }
        p_fixed_key = ctc_vector_del(p_usw_acl_master[lchip]->fixed_key_vec, p_fixed_key->key_type);
        mem_free(p_fixed_key);
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_FLEX_KEY, 1);
        return CTC_E_NONE;
    }

    CTC_MAX_VALUE_CHECK(acl_flex_key->origin_key_type, CTC_ACL_KEY_FLEX_BASE-1);
    if(!ACL_KEY_IS_TCAM(acl_flex_key->origin_key_type))
    {
        return CTC_E_INVALID_CONFIG;
    }
    if (!SYS_ACL_KEY_IS_FLEX(acl_flex_key->key_type))
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Invalid user key type, key_type:%u!\n", acl_flex_key->key_type);
        return CTC_E_INVALID_PARAM;
    }

    sal_memset(&pg, 0, sizeof(sys_acl_group_t));
    sal_memset(&ctc_entry, 0, sizeof(ctc_acl_entry_t));
    pg.group_info.dir = acl_flex_key->dir;
    ctc_entry.key_type = acl_flex_key->origin_key_type;
    CTC_ERROR_RETURN(sys_usw_acl_check_entry_type(lchip, 0, &pg, &ctc_entry));

    p_kset_base = p_usw_acl_master[lchip]->kset_db[acl_flex_key->origin_key_type];
    if (NULL == p_kset_base)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Invalid key type, key_type:%u!\n", acl_flex_key->origin_key_type);
        return CTC_E_NOT_SUPPORT;
    }
    p_kset_user = &acl_flex_key->kset;
    for (loop=0; loop<CTC_B2W_SIZE(CTC_FIELD_KEY_NUM); loop++)
    {
        if ((p_kset_user->w[loop] & (~p_kset_base->w[loop])) != 0)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Invalid user kset, kset index :%u!\n", loop);
            return CTC_E_INVALID_PARAM;
        }
    }

    cmd = DRV_IOR(FlowTcamLookupCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &flow_ctl);
    cmd = DRV_IOR(IpeAclQosCtl_t, IpeAclQosCtl_useGemPortLookup_f);
    DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &xgpon_use_gem_port);
    if (DRV_FROM_TMM(lchip))
    {
        mac_l3_ext_key_mac_sa_mode = GetFlowTcamLookupCtl(V,aclMacL3ExtKeyArpPktUseMacField_f,&flow_ctl) & 1;
        mac_l3_ext_key_mac_da_mode= GetFlowTcamLookupCtl(V,aclMacL3ExtKeyArpPktUseMacField_f,&flow_ctl) >> 1;
        mac_l3_key_mac_sa_mode = GetFlowTcamLookupCtl(V,aclMacL3BasicKeyArpPktUseMacField_f,&flow_ctl) & 1;
        mac_l3_key_mac_da_mode = GetFlowTcamLookupCtl(V,aclMacL3BasicKeyArpPktUseMacField_f,&flow_ctl) >> 1;
    }
    else
    {
        mac_l3_ext_key_mac_sa_mode = GetFlowTcamLookupCtl(V,aclMacL3ExtKeyArpPktUseSenderMac_f,&flow_ctl);
        mac_l3_ext_key_mac_da_mode= GetFlowTcamLookupCtl(V,aclMacL3ExtKeyArpPktUseTargetMac_f,&flow_ctl);
        mac_l3_key_mac_sa_mode = GetFlowTcamLookupCtl(V,aclMacL3BasicKeyArpPktUseSenderMac_f,&flow_ctl);
        mac_l3_key_mac_da_mode = GetFlowTcamLookupCtl(V,aclMacL3BasicKeyArpPktUseTargetMac_f,&flow_ctl);
    }
    if (!DRV_FROM_TMM(lchip))
    {
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP)
        {
            copp_key_use_ctag = GetFlowTcamLookupCtl(V, coppBasicKeyUseCtag_f, &flow_ctl);
            copp_key_use_l3l4_type = GetFlowTcamLookupCtl(V, coppBasicKeyEtherTypeShareType_f, &flow_ctl);/*default to 1*/
            copp_basic_key_ipaddr_use_ipsa = GetFlowTcamLookupCtl(V, coppKeyIpAddrShareType0_f, &flow_ctl); /*default to 0*/
            copp_key_use_udf = GetFlowTcamLookupCtl(V, coppBasicKeyUseUdfShareType_f, &flow_ctl) & 1;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP_EXT)
        {
            copp_key_use_ctag = GetFlowTcamLookupCtl(V, coppExtKeyUseCtag_f, &flow_ctl);
            copp_key_use_l3l4_type = GetFlowTcamLookupCtl(V, coppExtKeyEtherTypeShareType_f, &flow_ctl);/*default to 1*/
            copp_ext_key_ipv6sa = 1 & GetFlowTcamLookupCtl(V, coppKeyIpAddrShareType0_f, &flow_ctl); /*default to 1*/
            copp_ext_key_use_udf =  GetFlowTcamLookupCtl(V, coppExtKeyUdfShareType_f,&flow_ctl)?0:1;
        }
    }
    if (acl_flex_key->dir == CTC_INGRESS)
    {
        cid_key_v6_use_ipda = GetFlowTcamLookupCtl(V, ingrSgaclKeyIpv6PktUseIpDaField_f, &flow_ctl);

        cmd = DRV_IOR(IpePreLookupAclCtl_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_pre_lkup_ctl);
        l2type_use_vlanNum = GetIpePreLookupAclCtl(V, layer2TypeUsedAsVlanNum_f, &ipe_pre_lkup_ctl);
    }
    else
    {
        cid_key_v6_use_ipda = GetFlowTcamLookupCtl(V, egrSgaclKeyIpv6PktUseIpDaField_f, &flow_ctl);

        cmd = DRV_IOR(EpePktProcCtl_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &epe_pkt_proc_ctl);
        l2type_use_vlanNum = GetEpePktProcCtl(V, layer2TypeUsedAsVlanNum_f, &epe_pkt_proc_ctl);
    }
    copp_key_basic_mac_da_mode = !GetFlowTcamLookupCtl(V,coppBasicKeyDisableArpShareMacDa_f,&flow_ctl);
    short_key_use_svlan =  !GetFlowTcamLookupCtl(V,acl80bitKeyUseCvlan_f,&flow_ctl);
    arware_tunnel_info = !GetFlowTcamLookupCtl(V,array_0_ignorMergeMode_f,&flow_ctl);
    support_vsi_check = (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A && DRV_IS_TSINGMA(lchip)) ? 1 : 0;
    copp_key = (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP) || (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP_EXT);
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_FID) && support_vsi_check)
    {
        if ((acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP && 0 == GetFlowTcamLookupCtl(V, coppBasicKeySupportVsi_f, &flow_ctl))
            || (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP_EXT && 0 == GetFlowTcamLookupCtl(V, coppExtKeySupportVsi_f, &flow_ctl)))
        {
            return CTC_E_NOT_SUPPORT;
        }
        if ((acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD && 0 == GetFlowTcamLookupCtl(V, forwardingBasicKeySupportVsi_f, &flow_ctl))
            || (acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD_EXT && 0 == GetFlowTcamLookupCtl(V, forwardingExtKeySupportVsi_f, &flow_ctl)))
        {
            return CTC_E_NOT_SUPPORT;
        }
    }
    key_port_mode_check =   (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_PORT)?1:0)       +
                            (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_METADATA)?1:0)   +
                            (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SRC_CID)||SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DST_CID)?1:0);
    if (!(DRV_FROM_TMM(lchip) && (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV6
        ||acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4 )) && key_port_mode_check > 1)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Invalid user kset, port, metadata and cid can't be used together!\n");
        return CTC_E_PARAM_CONFLICT;
    }
    if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4 && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MAC_DA) && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_AWARE_TUNNEL_INFO))
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Invalid user kset, mac-da and aware-tunnel-info can't be used together!\n");
        return CTC_E_PARAM_CONFLICT;
    }
    vlan_mode |= (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SVLAN_ID)    ||
                          SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_STAG_CFI)    ||
                          SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_STAG_COS)    ||
                          SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_STAG_VALID)  ||
                          SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SVLAN_RANGE))?1:0;
    vlan_mode |= (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CVLAN_ID)    ||
                          SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CTAG_CFI)    ||
                          SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CTAG_COS)    ||
                          SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CTAG_VALID)  ||
                          SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CVLAN_RANGE))?2:0;
    if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC && vlan_mode == 3)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Invalid user kset, stag and ctag can't be used together!\n");
        return CTC_E_INVALID_PARAM;
    }
    if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4 && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_AWARE_TUNNEL_INFO) && CTC_IS_BIT_SET(vlan_mode, 1))
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Invalid user kset, ctag and aware-tunnel-info can't be used together!\n");
        return CTC_E_INVALID_PARAM;
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_GEM_PORT) && (!xgpon_use_gem_port || DRV_IS_DUET2(lchip) || DRV_FROM_TMM(lchip)))
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Gem port not support \n");
        return CTC_E_NOT_SUPPORT;
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MAC_SA))
    {
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4_EXT &&
            acl_flex_key->l3_type == CTC_PARSER_L3_TYPE_ARP &&
            mac_l3_ext_key_mac_sa_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_ext_key mac_sa_mode:%d \n", mac_l3_ext_key_mac_sa_mode);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4 &&
            acl_flex_key->l3_type  == CTC_PARSER_L3_TYPE_ARP &&
            mac_l3_key_mac_sa_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_key mac_sa_mode:%d \n", mac_l3_key_mac_sa_mode);
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MAC_DA))
    {
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4 &&
            acl_flex_key->l3_type  == CTC_PARSER_L3_TYPE_ARP &&
            mac_l3_key_mac_da_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_key mac_da_mode:%d \n", mac_l3_key_mac_da_mode);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP &&
            acl_flex_key->l3_type  == CTC_PARSER_L3_TYPE_ARP &&
            copp_key_basic_mac_da_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp_key mac_da_mode:%d \n", copp_key_basic_mac_da_mode);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4_EXT &&
            acl_flex_key->l3_type  == CTC_PARSER_L3_TYPE_ARP &&
            mac_l3_ext_key_mac_da_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_ext_key mac_da_mode:%d \n", mac_l3_ext_key_mac_da_mode);
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_STAG_VALID)   ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SVLAN_ID)     ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_STAG_COS)     ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_STAG_CFI)     ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SVLAN_RANGE))
    {
        if (copp_key && copp_key_use_ctag)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp_key copp_key_use_ctag:%d \n", copp_key_use_ctag);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_INTERFACE && !short_key_use_svlan)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "interface key use_svlan:%d \n", short_key_use_svlan);
            return CTC_E_INVALID_PARAM;
        }
        if(acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD && GetFlowTcamLookupCtl(V,aclForwardingBasicKeyUseCvlan_f,&flow_ctl))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "forward key in use cvlan mode\n");
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CVLAN_ID)   ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CTAG_COS)   ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CVLAN_RANGE)||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CTAG_VALID) ||
		SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CTAG_CFI))
    {
        if (copp_key && !copp_key_use_ctag)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp_key copp_key_use_ctag:%d \n", copp_key_use_ctag);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_INTERFACE && short_key_use_svlan)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "interface key use_svlan:%d \n", short_key_use_svlan);
            return CTC_E_INVALID_PARAM;
        }
        if(acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD && !GetFlowTcamLookupCtl(V,aclForwardingBasicKeyUseCvlan_f,&flow_ctl))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "forward key in use svlan mode\n");
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ETHER_TYPE))
    {
        if ((acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD       ||
             acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD_EXT   ||
             acl_flex_key->origin_key_type == CTC_ACL_KEY_IPV4      ||
             acl_flex_key->origin_key_type == CTC_ACL_KEY_IPV4_EXT  ||
             acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4  ||
             acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4_EXT) &&
            (CTC_PARSER_L3_TYPE_NONE != acl_flex_key->l3_type || 0x0806 == acl_flex_key->ether_type || 0x8035 == acl_flex_key->ether_type))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The Key's l3 type must be none l3_type:%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L2_TYPE))
    {
        if (l2type_use_vlanNum )
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The Key l2type_use_vlanNum:%d \n", l2type_use_vlanNum);
            return CTC_E_INVALID_PARAM;

        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VLAN_NUM))
    {
        if (!l2type_use_vlanNum )
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The Key l2type_use_vlanNum:%d \n", l2type_use_vlanNum);
            return CTC_E_INVALID_PARAM;

        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L3_TYPE))
    {
        if (copp_key && !copp_key_use_l3l4_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp_key  use_l3l4_type:%d \n", copp_key_use_l3l4_type);
            return CTC_E_INVALID_PARAM;
        }
        if(acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP && copp_key_use_udf)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp basic key now use udf\n");
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L4_TYPE))
    {
        if (copp_key && !copp_key_use_l3l4_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp_key  use_l3l4_type:%d \n", copp_key_use_l3l4_type);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD_EXT && (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "fwd_ext_key l3_type must be ipv4, Current L3 Type:%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
        if (CTC_PARSER_L3_TYPE_NONE == acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Current L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }

    key_l4_port_mode |= (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_GRE_KEY) || SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_NVGRE_KEY))?1:0;
    key_l4_port_mode |= (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VN_ID))?2:0;
    key_l4_port_mode |= (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ICMP_CODE)   ||
                         SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ICMP_TYPE)   ||
                         SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IGMP_TYPE)   ||
                         SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L4_DST_PORT) ||
                         SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L4_SRC_PORT))?4:0;
    key_l4_port_mode |= (!DRV_FROM_TMM(lchip) && (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TCP_ECN) || SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TCP_FLAGS)))?4:0;
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L4_USER_TYPE))
    {
        if (CTC_PARSER_L4_TYPE_NONE == acl_flex_key->l4_type || (key_l4_port_mode != 0 && key_l4_port_mode != 2 && acl_flex_key->l4_user_type == CTC_PARSER_L4_USER_TYPE_UDP_VXLAN))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Current L4 Type :%d \n", acl_flex_key->l4_type);
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_SA))
    {
		if (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv4, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
		if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP && (!copp_basic_key_ipaddr_use_ipsa) )
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_DA))
    {
        if (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv4, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
		if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP && copp_basic_key_ipaddr_use_ipsa)
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IPV6_SA))
    {
        if (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv6, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
		if(acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP)
		{
			SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp basic key no support ipv6 address\n");
            return CTC_E_INVALID_PARAM;
		}
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP_EXT && !copp_ext_key_ipv6sa  && copp_ext_key_use_udf)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp ext key , ipsa and udf share, now only use udf\n");
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_CID && cid_key_v6_use_ipda)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "cid_key , use_ipda :%d \n", cid_key_v6_use_ipda);
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IPV6_DA))
    {
        if (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv6, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
		if(acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP)
		{
			SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp basic key no support ipv6 address\n");
            return CTC_E_INVALID_PARAM;
		}
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP_EXT && (copp_ext_key_ipv6sa && copp_ext_key_use_udf))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp ext key , ipda and udf share same field,now only use udf\n");
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_CID && !cid_key_v6_use_ipda)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "cid_key , use_ipda :%d \n", cid_key_v6_use_ipda);
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IPV6_FLOW_LABEL))
    {
        if (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv6, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_TTL))
    {
        if (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4
            && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv6 or ipv4, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_DSCP))
    {
        if (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4 && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv6 or ipv4, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_PKT_LEN_RANGE)     ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L4_DST_PORT_RANGE)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L4_SRC_PORT_RANGE))
    {
        if (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4 && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv6 or ipv4, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_PROTOCOL)      ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_PRECEDENCE)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_ECN)           ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_FRAG)          ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_HDR_ERROR)     ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IP_OPTIONS))
    {
        if (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4 && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6 && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IP)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv6 or ipv4, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L4_DST_PORT) ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_L4_SRC_PORT))
    {
        if (CTC_PARSER_L3_TYPE_IPV4 != acl_flex_key->l3_type
            && CTC_PARSER_L3_TYPE_IPV6 != acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 Type is not Ipv6 or ipv4, L3 Type :%d \n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->l4_type == CTC_PARSER_L4_TYPE_NONE
            || CTC_PARSER_L4_TYPE_ICMP == acl_flex_key->l4_type
        || CTC_PARSER_L4_TYPE_IGMP == acl_flex_key->l4_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L4 port's L4 Type is conflict, L4 Type :%d \n", acl_flex_key->l4_type);
            return CTC_E_PARAM_CONFLICT;
        }
        if (!DRV_FROM_TMM(lchip) && key_l4_port_mode != 4 && key_l4_port_mode != 0)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L4 port's share is conflit, l4_port_mode:%d \n", key_l4_port_mode);
            return CTC_E_PARAM_CONFLICT;
        }

        if(CTC_PARSER_L4_USER_TYPE_UDP_VXLAN == acl_flex_key->l4_user_type || CTC_PARSER_L4_TYPE_GRE == acl_flex_key->l4_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L4 type is conflit, l4_type:%d, l4_user_type:%d.\n", acl_flex_key->l4_type, acl_flex_key->l4_user_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TCP_ECN) ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TCP_FLAGS))
    {
        if ((acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4  && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
            || (acl_flex_key->l4_type != CTC_PARSER_L4_TYPE_TCP))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "TCP param is mismatch , l3_type :%d l4_type:%d \n", acl_flex_key->l3_type, acl_flex_key->l4_type);
            return CTC_E_INVALID_PARAM;
        }
        if (!DRV_FROM_TMM(lchip) && key_l4_port_mode != 4 && key_l4_port_mode != 0 )
        {
            return CTC_E_PARAM_CONFLICT;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ICMP_CODE) ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ICMP_TYPE))
    {
        if ((acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4 && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
            || (acl_flex_key->l4_type != CTC_PARSER_L4_TYPE_ICMP))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Param is mismatch , l3_type :%d l4_type:%d \n", acl_flex_key->l3_type, acl_flex_key->l4_type);
            return CTC_E_INVALID_PARAM;
        }
        if (!DRV_FROM_TMM(lchip) && key_l4_port_mode != 4 && key_l4_port_mode != 0)
        {
            return CTC_E_PARAM_CONFLICT;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IGMP_TYPE))
    {
        if ((acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4 && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
            || (acl_flex_key->l4_type != CTC_PARSER_L4_TYPE_IGMP))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Param is mismatch , l3_type :%d l4_type:%d \n", acl_flex_key->l3_type, acl_flex_key->l4_type);
            return CTC_E_INVALID_PARAM;
        }
        if (!DRV_FROM_TMM(lchip) && key_l4_port_mode != 4 && key_l4_port_mode != 0)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "share filed key_l4_port_mode:%d \n", key_l4_port_mode);
            return CTC_E_PARAM_CONFLICT;
        }
    }
    key_mergedata_mode |= (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_WLAN_CTL_PKT)      ||
                           SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_WLAN_RADIO_MAC)    ||
                           SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_WLAN_RADIO_ID))?1:0;
    key_mergedata_mode |= SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_AWARE_TUNNEL_INFO)?2:0;
    key_mergedata_mode |= ((SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VXLAN_RSV1) || SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VXLAN_RSV2)) &&
                           (CTC_ACL_KEY_IPV6_EXT == acl_flex_key->origin_key_type || CTC_ACL_KEY_MAC_IPV6 == acl_flex_key->origin_key_type))?1:0;
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VXLAN_FLAGS)  ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VXLAN_RSV1)   ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VXLAN_RSV2))
    {
        if ((acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4 && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
            || (acl_flex_key->l4_type != CTC_PARSER_L4_TYPE_UDP)
            || (acl_flex_key->l4_user_type != CTC_PARSER_L4_USER_TYPE_UDP_VXLAN))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Param is mismatch , l3_type :%d l4_type:%d \n", acl_flex_key->l3_type, acl_flex_key->l4_type);
            return CTC_E_INVALID_PARAM;
        }
        if (!SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VXLAN_FLAGS) && (acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD || acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD_EXT) && (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "fwd and fwd ext key support the field only for ipv4 packet \n");
            return CTC_E_NOT_SUPPORT;
        }
        if (!SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VXLAN_FLAGS) && (acl_flex_key->origin_key_type == CTC_ACL_KEY_IPV6_EXT || CTC_ACL_KEY_MAC_IPV6 == acl_flex_key->origin_key_type) && (key_mergedata_mode & 2))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Merge Key check conflict,key_mergedata_mode:%d \n", key_mergedata_mode);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_VN_ID))
    {
        if ((acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4 && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
            || (acl_flex_key->l4_type != CTC_PARSER_L4_TYPE_UDP)
        || (acl_flex_key->l4_user_type != CTC_PARSER_L4_USER_TYPE_UDP_VXLAN))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Param is mismatch , l3_type :%d l4_type:%d \n", acl_flex_key->l3_type, acl_flex_key->l4_type);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP_EXT)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp ext key not support the field\n");
            return CTC_E_INVALID_PARAM;
        }
        if (key_l4_port_mode != 2 && key_l4_port_mode != 0 )
        {
            return CTC_E_PARAM_CONFLICT;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_GRE_KEY) || SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_NVGRE_KEY))
    {
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP_EXT)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp ext key not support the field\n");
            return CTC_E_INVALID_PARAM;
        }
        if ((acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4 && acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV6)
            || (acl_flex_key->l4_type != CTC_PARSER_L4_TYPE_GRE))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "param is mismatch , l3_type :%d l4_type:%d \n", acl_flex_key->l3_type, acl_flex_key->l4_type);
            return CTC_E_INVALID_PARAM;
        }

        if (key_l4_port_mode != 1 && key_l4_port_mode != 0 )
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "share filed key_l4_port_mode:%d \n", key_l4_port_mode);
            return CTC_E_PARAM_CONFLICT;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ARP_OP_CODE)          ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ARP_PROTOCOL_TYPE)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ARP_SENDER_IP)        ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ARP_TARGET_IP)        ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ARP_MAC_DA_CHK_FAIL)  ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ARP_MAC_SA_CHK_FAIL)  ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ARP_SENDERIP_CHK_FAIL) ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ARP_TARGETIP_CHK_FAIL) ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SENDER_MAC)           ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TARGET_MAC)           ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_GARP)                 ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_RARP))
    {
        if (CTC_PARSER_L3_TYPE_ARP != acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 type is not ARP l3 type:%d\n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4_EXT
            && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SENDER_MAC)
        && !mac_l3_ext_key_mac_sa_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_ext_key mac_sa_mode:%d \n", mac_l3_ext_key_mac_sa_mode);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4_EXT
            && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TARGET_MAC)
        && !mac_l3_ext_key_mac_da_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_ext_key mac_da_mode:%d \n", mac_l3_ext_key_mac_da_mode);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4
            && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SENDER_MAC)
        && !mac_l3_key_mac_sa_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_key mac_sa_mode:%d \n", mac_l3_key_mac_sa_mode);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4
            && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TARGET_MAC)
        && !mac_l3_key_mac_da_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_key mac_da_mode:%d \n", mac_l3_key_mac_da_mode);
            return CTC_E_INVALID_PARAM;
        }
        if (((acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4 && DRV_IS_DUET2(lchip)) || acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP)
            && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TARGET_MAC))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "key not support the field\n");
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP
            && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SENDER_MAC)
        && !copp_key_basic_mac_da_mode)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp_key mac_da_mode:%d \n", copp_key_basic_mac_da_mode);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_LABEL_NUM)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_LABEL0)  ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_EXP0)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_SBIT0)   ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_TTL0)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_LABEL1)  ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_EXP1)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_SBIT1)   ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_TTL1)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_LABEL2)  ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_EXP2)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_SBIT2)   ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MPLS_TTL2))
    {
        if (CTC_PARSER_L3_TYPE_MPLS != acl_flex_key->l3_type && CTC_PARSER_L3_TYPE_MPLS_MCAST!=acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 type is not MPLS l3 type:%d\n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_INTERFACE_ID))
    {
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_IPV4 && (CTC_PARSER_L3_TYPE_MPLS != acl_flex_key->l3_type) && (CTC_PARSER_L3_TYPE_MPLS_MCAST!=acl_flex_key->l3_type))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "when l3_key use interface id ,the pkt must be mpls :%d\n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IS_Y1731_OAM))
    {
        if(CTC_PARSER_L4_USER_TYPE_ACHOAM_ACHY1731 != acl_flex_key->l4_user_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Y1731 l4 user type must be ach oam\n");
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ETHER_OAM_LEVEL)      ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ETHER_OAM_OP_CODE)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_ETHER_OAM_VERSION))
    {
        if (DRV_FROM_TMM(lchip) && (CTC_PARSER_L3_TYPE_ETHER_OAM != acl_flex_key->l3_type))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Y1731 oam not support \n");
            return CTC_E_NOT_SUPPORT;
        }
        if (!(CTC_PARSER_L3_TYPE_ETHER_OAM == acl_flex_key->l3_type
            || SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IS_Y1731_OAM)))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Param is mismatch: l3_type:%d l4_type:%d,l4_user_type:%d\n", acl_flex_key->l3_type, acl_flex_key->l4_type, acl_flex_key->l4_user_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SLOW_PROTOCOL_CODE)   ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SLOW_PROTOCOL_FLAGS)  ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SLOW_PROTOCOL_SUB_TYPE))
    {
        if (CTC_PARSER_L3_TYPE_SLOW_PROTO != acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 type is not slow protocol l3_type:%d\n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_PTP_MESSAGE_TYPE) ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_PTP_VERSION))
    {
        if (CTC_PARSER_L3_TYPE_PTP != acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 type is not PTP  l3_type:%d\n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_FCOE_DST_FCID) ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_FCOE_SRC_FCID))
    {
        if (CTC_PARSER_L3_TYPE_FCOE != acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 type is not FCOE l3_type:%d\n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_INGRESS_NICKNAME)         ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_EGRESS_NICKNAME)          ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IS_ESADI)                 ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_IS_TRILL_CHANNEL)         ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TRILL_INNER_VLANID)       ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TRILL_INNER_VLANID_VALID) ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TRILL_LENGTH)             ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TRILL_MULTIHOP)           ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TRILL_MULTICAST)          ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TRILL_VERSION)            ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_TRILL_TTL))
    {
        if (CTC_PARSER_L3_TYPE_TRILL != acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 type is not TRILL l3_type:%d\n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_UNKNOW_PKT)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_ES)            ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_SC)            ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_AN)            ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_SL)            ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_PN)            ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_SCI)           ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_CBIT)          ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_EBIT)          ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_SCB)           ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DOT1AE_VER))
    {
        if (CTC_PARSER_L3_TYPE_DOT1AE != acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 type is not DOT1AE l3_type:%d\n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SATPDU_MEF_OUI)       ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SATPDU_OUI_SUB_TYPE)  ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SATPDU_PDU_BYTE))
    {
        if (CTC_PARSER_L3_TYPE_SATPDU != acl_flex_key->l3_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "L3 type is not SATPDU l3_type:%d\n", acl_flex_key->l3_type);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_WLAN_RADIO_MAC)   ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_WLAN_RADIO_ID)    ||
        SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_WLAN_CTL_PKT))
    {
        if (CTC_PARSER_L4_TYPE_UDP != acl_flex_key->l4_type
            && CTC_PARSER_L4_USER_TYPE_UDP_CAPWAP != acl_flex_key->l4_user_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "WLAN param is mismatch l3_type:%d l4_user_type:%d\n", acl_flex_key->l4_type, acl_flex_key->l4_user_type);
            return CTC_E_INVALID_PARAM;
        }
        if (key_mergedata_mode != 1 && key_mergedata_mode != 0)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Merge Key check conflict,key_mergedata_mode:%d \n", key_mergedata_mode);
            return CTC_E_INVALID_PARAM;
        }
    }
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_UDF) || SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_UDF_AD_ID))
    {
        if (acl_flex_key->origin_key_type != CTC_ACL_KEY_FWD_EXT        &&
            acl_flex_key->origin_key_type != CTC_ACL_KEY_UDF            &&
            acl_flex_key->origin_key_type != CTC_ACL_KEY_IPV6_EXT       &&
            acl_flex_key->origin_key_type != CTC_ACL_KEY_MAC_IPV4_EXT   &&
            !copp_key)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "UDF must use fwd_ext_key ipv6_ext_key or udf_key or mac l3 ext key or copp ext key\n");
            return CTC_E_INVALID_PARAM;
        }

        if(acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP_EXT && !copp_ext_key_use_udf)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp_ext_key udf and ip v6 address is share & now only use ip v6 address\n");
            return CTC_E_INVALID_PARAM;
        }
        if(acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP && !copp_key_use_udf)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "copp basic key now use l3 info\n");
            return CTC_E_INVALID_PARAM;
        }
    }
    macl3basic_key_cvlan_mode |= (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CTAG_VALID)  ||
                                  SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CVLAN_ID)    ||
                                  SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CTAG_COS)    ||
                                  SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CTAG_CFI)    ||
                                  SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_CVLAN_RANGE)) && acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4?1:0;
    macl3basic_key_cvlan_mode |= (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_AWARE_TUNNEL_INFO) && acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4)?2:0;
    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_AWARE_TUNNEL_INFO))
    {
        if(acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD_EXT && (acl_flex_key->l3_type != CTC_PARSER_L3_TYPE_IPV4))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Only ipv4 packet support aware tunnel info in fwd ext key\n");
            return CTC_E_INVALID_PARAM;
        }
        if (key_mergedata_mode != 2 && key_mergedata_mode != 0)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Merge Key check conflict,key_mergedata_mode:%d \n", key_mergedata_mode);
            return CTC_E_INVALID_PARAM;
        }
        if (CTC_PARSER_L4_TYPE_UDP == acl_flex_key->l4_type
            && CTC_PARSER_L4_USER_TYPE_UDP_VXLAN == acl_flex_key->l4_user_type)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The filed must be decapsulated packet, l4_type:%d,l4_user_type:%d\n", acl_flex_key->l4_type, acl_flex_key->l4_user_type);
            return CTC_E_INVALID_PARAM;
        }
        if (CTC_PARSER_L4_TYPE_UDP == acl_flex_key->l4_type
            && CTC_PARSER_L4_USER_TYPE_UDP_CAPWAP == acl_flex_key->l4_user_type )
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The filed must be decapsulated packet, l4_type:%d,l4_user_type:%d\n", acl_flex_key->l4_type, acl_flex_key->l4_user_type);
            return CTC_E_INVALID_PARAM;
        }
        if (CTC_PARSER_L4_TYPE_GRE == acl_flex_key->l4_type )
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The filed must be decapsulated packet, l4_type:%d,l4_user_type:%d\n", acl_flex_key->l4_type, acl_flex_key->l4_user_type);
            return CTC_E_INVALID_PARAM;
        }
        if (!arware_tunnel_info)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The filed must be decapsulated packet, arware_tunnel_info:%d\n", arware_tunnel_info);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4 && (macl3basic_key_cvlan_mode != 2 && macl3basic_key_cvlan_mode != 0))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_basic_key cvlan_mode:%d \n", macl3basic_key_cvlan_mode);
            return CTC_E_INVALID_PARAM;
        }
        if (acl_flex_key->origin_key_type == CTC_ACL_KEY_MAC_IPV4 && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_MAC_DA))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "mac_l3_basic_key mac_da used! \n");
            return CTC_E_INVALID_PARAM;
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DST_NHID))
    {
        if(support_vsi_check)
        {
            if ( (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP && 1 == GetFlowTcamLookupCtl(V, coppBasicKeySupportVsi_f, &flow_ctl))
            || (acl_flex_key->origin_key_type == CTC_ACL_KEY_COPP_EXT && 1 == GetFlowTcamLookupCtl(V, coppExtKeySupportVsi_f, &flow_ctl)) )
            {
                return CTC_E_NOT_SUPPORT;
            }
            if ((acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD && 1 == GetFlowTcamLookupCtl(V, forwardingBasicKeySupportVsi_f, &flow_ctl))
            || (acl_flex_key->origin_key_type == CTC_ACL_KEY_FWD_EXT && 1 == GetFlowTcamLookupCtl(V, forwardingExtKeySupportVsi_f, &flow_ctl)))
            {
                return CTC_E_NOT_SUPPORT;
            }
        }
    }

    if (SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_SRC_CID))
    {
        CTC_ERROR_RETURN(sys_usw_global_get_logic_destport_en(lchip,&service_queue_egress_en));
        if(acl_flex_key->dir == CTC_EGRESS && service_queue_egress_en)
        {
            return CTC_E_NOT_SUPPORT;
        }
    }

    if (!DRV_IS_DUET2(lchip) && SYS_ACL_PKSET_TEST(p_kset_user, CTC_FIELD_KEY_DECAP) && CTC_INGRESS != acl_flex_key->dir)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Egress not support decap \n");
        return CTC_E_NOT_SUPPORT;
    }


    p_fixed_key = mem_malloc(MEM_ACL_MODULE, sizeof(sys_acl_fixed_key_t));
    if (NULL == p_fixed_key)
    {
        return CTC_E_NO_MEMORY;
    }
    p_fixed_key->node_type = SYS_ACL_FLEX_KEY_NODE_FIXED;
    p_fixed_key->dir = acl_flex_key->dir;
    p_fixed_key->key_type = acl_flex_key->key_type;
    p_fixed_key->origin_key_type = acl_flex_key->origin_key_type;
    p_fixed_key->l3_type = acl_flex_key->l3_type;
    p_fixed_key->l4_type = acl_flex_key->l4_type;
    p_fixed_key->l4_user_type = acl_flex_key->l4_user_type;
    p_fixed_key->eth_type = acl_flex_key->ether_type;
    p_fixed_key->entry_count = 0;
    sal_memcpy(&p_fixed_key->kset, &acl_flex_key->kset, sizeof(sys_acl_kset_t));
    if (FALSE == ctc_vector_add(p_usw_acl_master[lchip]->fixed_key_vec, acl_flex_key->key_type, p_fixed_key))
    {
        mem_free(p_fixed_key);
        return CTC_E_NO_MEMORY;
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_FLEX_KEY, 1);
    return CTC_E_NONE;
}

int32
sys_usw_acl_set_flex_key_fields(uint8 lchip, ctc_acl_flex_key_t* acl_flex_key)
{
    int32  ret = CTC_E_NONE;
    uint8  is_flex_hash = 0;
    /*1. Sanity Check*/
    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_PTR_VALID_CHECK(acl_flex_key);
    SYS_ACL_FK_TYPE_VALID_CHECK(acl_flex_key->key_type);
    CTC_MAX_VALUE_CHECK(acl_flex_key->dir, CTC_BOTH_DIRECTION-1);

    SYS_USW_ACL_LOCK(lchip);
    is_flex_hash = CTC_FLAG_ISSET(acl_flex_key->flag, CTC_ACL_FLEX_KEY_FLAG_HASH)? 1: 0;
    if (!DRV_FROM_TMM(lchip) || ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && acl_flex_key->dir == CTC_EGRESS))
    {
        ret = _sys_usw_acl_set_key_fields(lchip, acl_flex_key);
    }
    else if (NULL != p_usw_acl_master[lchip]->set_flex_key_fields[is_flex_hash])
    {
        ret = p_usw_acl_master[lchip]->set_flex_key_fields[is_flex_hash](lchip, acl_flex_key);
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}
extern int32
_sys_usw_acl_get_flex_key_fields(uint8 lchip, ctc_acl_flex_key_t * acl_flex_key);
int32
sys_usw_acl_get_flex_key_fields(uint8 lchip, ctc_acl_flex_key_t* acl_flex_key)
{
    int32  ret = CTC_E_NONE;
    /*1. Sanity Check*/
    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_PTR_VALID_CHECK(acl_flex_key);
    SYS_ACL_FK_TYPE_VALID_CHECK(acl_flex_key->key_type);

    SYS_USW_ACL_LOCK(lchip);

    if (NULL == MCHIP_ACL(lchip)->get_flex_key_fields)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_SUPPORT;
    }
    if (((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && acl_flex_key->dir == CTC_EGRESS) || !DRV_FROM_TMM(lchip))
    {
        ret = _sys_usw_acl_get_flex_key_fields(lchip, acl_flex_key);
    }
    else
    {
        ret = MCHIP_ACL(lchip)->get_flex_key_fields(lchip, acl_flex_key);
    }

    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_set_aset_fields(uint8 lchip, ctc_acl_aset_t* ctc_aset)
{
    int32 ret = 0;
    sys_acl_aset_t * p_sys_aset = NULL;
    uint32 zeros[CTC_B2W_SIZE(CTC_ACL_FIELD_ACTION_NUM)] = {0};
    uint8 is_set = 1;

    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_PTR_VALID_CHECK(ctc_aset);
    if(SYS_ACL_ASET_IS_DEF(ctc_aset->aset_id))
    {
        return CTC_E_INVALID_PARAM;
    }
    if(0 == sal_memcmp(&ctc_aset->w, zeros, sizeof(zeros)))
    {
        is_set = 0;
    }

    lchip = drv_vchip_get_pp_base(lchip);
    SYS_USW_ACL_LOCK(lchip);
    _sys_usw_acl_get_aset(lchip, ctc_aset->aset_id, &p_sys_aset);
    if((p_sys_aset == NULL) != is_set )
    {
        ret = is_set ? CTC_E_ENTRY_EXIST : CTC_E_ENTRY_NOT_EXIST;
        goto done;
    }
    ret = is_set ? _sys_usw_acl_add_aset(lchip, ctc_aset->type, ctc_aset, &p_sys_aset) :
                   (p_sys_aset->ref_cnt ? CTC_E_IN_USE : _sys_usw_acl_remove_aset(lchip, ctc_aset->aset_id));
    if(is_set && p_sys_aset)
    {
        p_sys_aset->is_static = 1;
    }

done:
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}


int32
sys_usw_acl_get_aset_fields(uint8 lchip, ctc_acl_aset_t* ctc_aset)
{
    int32 ret = 0;
    uint16 aset_id = 0;
    sys_acl_aset_t * p_sys_aset = NULL;

    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_PTR_VALID_CHECK(ctc_aset);
    CTC_MAX_VALUE_CHECK(ctc_aset->aset_id, 0xFF);

    SYS_USW_ACL_LOCK(lchip);
    aset_id = ctc_aset->aset_id;
    if(!ctc_aset->aset_id)
    {
        aset_id = (1 == ctc_aset->type) ? SYS_ACL_DEF_ASET_EGS_TCAM : ((2 == ctc_aset->type) ? SYS_ACL_DEF_ASET_HASH : 0);
    }
    ret = _sys_usw_acl_get_aset(lchip, aset_id, &p_sys_aset);
    if(p_sys_aset)
    {
        sal_memcpy(ctc_aset->w, &p_sys_aset->w, sizeof(ctc_aset->w));
        ctc_aset->xdata_prof_id = p_sys_aset->xdata_prof_id;
        ctc_aset->type = p_sys_aset->type;
    }
    SYS_USW_ACL_UNLOCK(lchip);

    return ret;
}



int32
sys_usw_acl_create_presel(uint8 lchip, ctc_acl_presel_t* acl_presel)
{
    int32  ret = CTC_E_NONE;
    /*1. Sanity Check*/
    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_PTR_VALID_CHECK(acl_presel);
    CTC_MAX_VALUE_CHECK(acl_presel->presel_id, SYS_ACL_PRESEL_ID_MAX);

    SYS_USW_ACL_LOCK(lchip);

    if (NULL == MCHIP_ACL(lchip)->create_presel)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_SUPPORT;
    }
    ret = MCHIP_ACL(lchip)->create_presel(lchip, acl_presel);

    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}
int32
sys_usw_acl_destroy_presel(uint8 lchip, uint16 presel_id)
{
    int32  ret = CTC_E_NONE;
    /*1. Sanity Check*/
    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_MAX_VALUE_CHECK(presel_id, SYS_ACL_PRESEL_ID_MAX);

    SYS_USW_ACL_LOCK(lchip);

    if (NULL == MCHIP_ACL(lchip)->destroy_presel)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_SUPPORT;
    }
    ret = MCHIP_ACL(lchip)->destroy_presel(lchip, presel_id);

    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_add_presel_fields(uint8 lchip, uint16 presel_id, uint8 fields_cnt, ctc_field_key_t *fields)
{
    int32  ret = CTC_E_NONE;
    /*1. Sanity Check*/
    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_MAX_VALUE_CHECK(presel_id, SYS_ACL_PRESEL_ID_MAX);
    CTC_PTR_VALID_CHECK(fields);

    SYS_USW_ACL_LOCK(lchip);

    if (NULL == MCHIP_ACL(lchip)->add_presel_fields)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_SUPPORT;
    }
    ret = MCHIP_ACL(lchip)->add_presel_fields(lchip, presel_id, fields_cnt, fields);

    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_remove_presel_fields(uint8 lchip, uint16 presel_id, uint8 fields_cnt, ctc_field_key_t *fields)
{
    int32  ret = CTC_E_NONE;
    /*1. Sanity Check*/
    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_MAX_VALUE_CHECK(presel_id, SYS_ACL_PRESEL_ID_MAX);
    CTC_PTR_VALID_CHECK(fields);

    SYS_USW_ACL_LOCK(lchip);

    if (NULL == MCHIP_ACL(lchip)->remove_presel_fields)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_SUPPORT;
    }
    ret = MCHIP_ACL(lchip)->remove_presel_fields(lchip, presel_id, fields_cnt, fields);

    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

#define _ACL_GROUP_

/*
 * create an acl group.
 * For init api, group_info can be NULL.
 * For out using, group_info must not be NULL.
 *
 */
int32
sys_usw_acl_create_group(uint8 lchip, uint32 group_id, ctc_acl_group_info_t* group_info)
{
    sys_acl_group_t* pg = NULL;
    int32 ret;


    /*1. Sanity Check*/
    SYS_ACL_INIT_CHECK();
    SYS_ACL_CHECK_GROUP_ID(group_id);
    SYS_ACL_CHECK_RSV_GROUP_ID(group_id); /* reserve group cannot be created by user */
    /* check if priority bigger than biggest priority */

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: group_id: %u \n", group_id);

    /*
     *  group_id is uint32.
     *  #1 check block_num from p_p_usw_acl_master[lchip]. precedence cannot bigger than block_num.
     *  #2 malloc a sys_acl_group_t, add to hash based on group_id.
     */

    SYS_USW_ACL_LOCK(lchip);

    /*2. Check if group exist */
    _sys_usw_acl_get_group_by_gid(lchip, group_id, &pg);
    if (pg)
    {
        ret = CTC_E_EXIST;
        goto error0;
    }

    /*3. Alloc group node and insert to DB*/
    ret = _sys_usw_acl_create_group(lchip, group_id, group_info);
    if (ret)
    {
        goto error0;
    }

    SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NONE);

error0:
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

/*
 * destroy an empty group.
 */
int32
sys_usw_acl_destroy_group(uint8 lchip, uint32 group_id)
{
    SYS_ACL_INIT_CHECK();
    SYS_ACL_CHECK_GROUP_ID(group_id);
    SYS_ACL_CHECK_RSV_GROUP_ID(group_id); /* reserve group cannot be destroyed */

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: group_id: %u \n", group_id);

    /*
     * #1 check if entry all removed.
     * #2 remove from hash. free sys_acl_group_t.
     */
    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_destroy_group(lchip, group_id));

    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

/*
 * install a group (empty or NOT) to hardware table
 */
int32
sys_usw_acl_install_group(uint8 lchip, uint32 group_id, ctc_acl_group_info_t* group_info)
{
    SYS_ACL_INIT_CHECK();
    SYS_ACL_CHECK_GROUP_ID(group_id);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: gid %u  \n", group_id);

    SYS_USW_ACL_LOCK(lchip);
    /* get group node */
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_install_group(lchip, group_id, group_info));

    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

/*
 * uninstall a group (empty or NOT) from hardware table
 */
int32
sys_usw_acl_uninstall_group(uint8 lchip, uint32 group_id)
{
    SYS_ACL_INIT_CHECK();
    SYS_ACL_CHECK_GROUP_ID(group_id);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: gid %u \n", group_id);

    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_uninstall_group(lchip, group_id));

    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

/*
 * get group info by group id. NOT For hash group.
 */
int32
sys_usw_acl_get_group_info(uint8 lchip, uint32 group_id, ctc_acl_group_info_t* group_info)
{
    sys_acl_group_info_t* pinfo = NULL;  /* sys group info */
    sys_acl_group_t     * pg    = NULL;
    sys_acl_aset_t* p_aset = NULL;

    SYS_ACL_INIT_CHECK();
    SYS_ACL_CHECK_GROUP_ID(group_id);

    CTC_PTR_VALID_CHECK(group_info);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: gid: %u \n", group_id);

    _sys_usw_acl_get_group_by_gid(lchip, group_id, &pg);
    SYS_ACL_CHECK_GROUP_UNEXIST(pg);

    pinfo = &(pg->group_info);
    if(group_info->aset)
    {
        group_info->aset->aset_id = pg->aset_id;
        _sys_usw_acl_get_aset(lchip, pg->aset_id, &p_aset);
        if(p_aset)
        {
            sal_memcpy(group_info->aset->w, p_aset->w, sizeof(p_aset->w));
        }
    }

    /* get ctc group info based on pinfo (sys group info) */
    CTC_ERROR_RETURN(_sys_usw_acl_unmap_group_info(lchip, group_info, pinfo));

    return CTC_E_NONE;
}

#define _ACL_ENTRY_

/*
 * install entry to hardware table
 */
int32
sys_usw_acl_install_entry(uint8 lchip, uint32 eid)
{
    sys_acl_entry_t* pe;
    SYS_ACL_INIT_CHECK();

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: eid %u \n", eid);

    SYS_USW_ACL_LOCK(lchip);
	_sys_usw_acl_get_entry_by_eid(lchip, eid, &pe);
    if (!pe)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not found \n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_EXIST);
    }
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_install_entry(lchip, pe, SYS_ACL_ENTRY_OP_FLAG_ADD, 1));
    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

/*
 * uninstall entry from hardware table
 */
int32
sys_usw_acl_uninstall_entry(uint8 lchip, uint32 eid)
{
    sys_acl_entry_t* pe;
    SYS_ACL_INIT_CHECK();

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: eid %u \n", eid);

    SYS_USW_ACL_LOCK(lchip);
    _sys_usw_acl_get_entry_by_eid(lchip, eid, &pe);
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_install_entry(lchip, pe, SYS_ACL_ENTRY_OP_FLAG_DELETE, 1));
    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_acl_add_key_field(uint8 lchip, uint32 entry_id, ctc_field_key_t* key_field)
{
    sys_acl_entry_t* pe_lkup = NULL;

    /*1. Sanity Check*/
    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(key_field);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "  %% PARAM: eid %u -- key_field %u\n", entry_id, key_field->type);

    SYS_USW_ACL_LOCK(lchip);
    /*2. Add entry field*/
    /*get entry and check*/
    _sys_usw_acl_get_entry_by_eid(lchip, entry_id, &pe_lkup);
    if (!pe_lkup )
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Entry not exist \n");
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_operate_key_field(lchip, pe_lkup, key_field, 1));
    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_acl_remove_key_field(uint8 lchip, uint32 entry_id, ctc_field_key_t* key_field)
{
    sys_acl_entry_t* pe_lkup = NULL;
    /*1. Sanity Check*/
    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(key_field);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: eid %u -- key_field %u\n", entry_id, key_field->type);

    SYS_USW_ACL_LOCK(lchip);
    _sys_usw_acl_get_entry_by_eid(lchip, entry_id, &pe_lkup);

    if (!pe_lkup)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not found \n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_EXIST);
    }
    /* hash entry not support remove key field */
    if (!ACL_ENTRY_IS_TCAM(pe_lkup))
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " API or some feature is not supported \n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_SUPPORT);
    }
    /*2. Remove entry field*/
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_operate_key_field(lchip, pe_lkup, key_field, 0));

    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_acl_remove_action_field(uint8 lchip, sys_acl_entry_t* pe_lkup, ctc_acl_field_action_t* action_field)
{
    uint8 is_half_ad = 0;
    uint32 key_id = 0;
    uint32 act_id = 0;
    uint32 hw_index = 0;
    int32 ret = CTC_E_NONE;
    ds_t   old_action = {0};
    sys_acl_aset_t*  aset = NULL;

    if (CTC_ACL_FIELD_ACTION_LB_HASH_PROFILE == action_field->type)
    {
        action_field->type = CTC_ACL_FIELD_ACTION_LB_HASH_ECMP_PROFILE;
        _sys_usw_acl_remove_action_field(lchip, pe_lkup, action_field);
        action_field->type = CTC_ACL_FIELD_ACTION_LB_HASH_LAG_PROFILE;
        _sys_usw_acl_remove_action_field(lchip, pe_lkup, action_field);
        action_field->type = CTC_ACL_FIELD_ACTION_LB_HASH_PROFILE;
        return CTC_E_NONE;
    }

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: action_field %u\n", action_field->type);

    /* aset check*/
    CTC_ERROR_RETURN(_sys_usw_acl_get_aset(lchip, pe_lkup->aset_id, &aset));
    if(!CTC_BMP_ISSET(aset->w, action_field->type))
    {
        return CTC_E_NONE;
    }

    if(ACL_ENTRY_IS_INSTALLED(pe_lkup))
    {
        /*1. rebuild buffer; if hash ad, copy buffer to new_buffer*/
        /*2. update action buffer(if hash, up new_buffer)*/
        SYS_ACL_GET_TBL_FUNC(lchip, pe_lkup, &key_id, &act_id, &hw_index);
        CTC_ERROR_RETURN(
            _sys_usw_acl_rebuild_buffer_from_hw(lchip, key_id, act_id, hw_index, pe_lkup));
        if(!ACL_ENTRY_IS_TCAM(pe_lkup))
        {
            sal_memcpy(old_action, pe_lkup->ua->buffer.action, sizeof(ds_t));
            SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_HASH_ENTRY, 1);
        }
        else
        {
            SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY, 1);
        }
    }

    if (ACL_ENTRY_IS_TCAM(pe_lkup))
    {
        if (CTC_ACL_KEY_INTERFACE == pe_lkup->key_type)
        {
            is_half_ad = 1;
        }

        if (DRV_FROM_TMM(lchip) && CTC_EGRESS == pe_lkup->group->group_info.dir)
        {
            CTC_ERROR_GOTO(MCHIP_ACL(lchip)->add_egs_action_field(lchip, action_field, pe_lkup, FALSE), ret, error1);
        }
        else
        {
            switch(action_field->type)
            {
            case CTC_ACL_FIELD_ACTION_COLOR:
            case CTC_ACL_FIELD_ACTION_PRIORITY:
            case CTC_ACL_FIELD_ACTION_QOS_TABLE_MAP:
            case CTC_ACL_FIELD_ACTION_CANCEL_DISCARD:
            case CTC_ACL_FIELD_ACTION_DISCARD:
            case CTC_ACL_FIELD_ACTION_REDIRECT_PORT:
            case CTC_ACL_FIELD_ACTION_REDIRECT:
            case CTC_ACL_FIELD_ACTION_MICRO_FLOW_POLICER:
            case CTC_ACL_FIELD_ACTION_MACRO_FLOW_POLICER:
            case CTC_ACL_FIELD_ACTION_COS_HBWP_POLICER:
            case CTC_ACL_FIELD_ACTION_STATS:
            case CTC_ACL_FIELD_ACTION_CP_TO_CPU:
            case CTC_ACL_FIELD_ACTION_IPFIX:
            case CTC_ACL_FIELD_ACTION_IPFIX_HASH_SALT:
            case CTC_ACL_FIELD_ACTION_CANCEL_IPFIX:
            case CTC_ACL_FIELD_ACTION_CANCEL_IPFIX_LEARNING:
            case CTC_ACL_FIELD_ACTION_RANDOM_LOG:
            case CTC_ACL_FIELD_ACTION_XDATA:
            CTC_ERROR_GOTO(_sys_usw_acl_add_dsacl_field2(lchip, action_field, pe_lkup, is_half_ad, 0), ret, error1);
            break;
            default:
            CTC_ERROR_GOTO(_sys_usw_acl_add_dsacl_field(lchip, action_field, pe_lkup, is_half_ad, 0), ret, error1);
            break;
            }
        }
    }
    else
    {
        CTC_ERROR_GOTO(_sys_usw_acl_add_dsflow_field(lchip, action_field, (sys_acl_hash_entry_t*)pe_lkup, 0), ret, error0);
    }

    /*3. if entry is installed,
     *   for tcam, add action to hw, free buffer
     *   for hash, call add_hw, input old_action and new_action(to update spool)
    */
    if(ACL_ENTRY_IS_INSTALLED(pe_lkup))
    {
        CTC_ERROR_GOTO(_sys_usw_acl_add_hw(lchip, pe_lkup, old_action), ret, error0);
    }

    return CTC_E_NONE;
error1:
    if(ACL_ENTRY_IS_INSTALLED(pe_lkup) && pe_lkup->ad_type != SYS_ACL_AD_TYPE_DISABLE)
    {
        _sys_usw_acl_map_action_data(lchip, pe_lkup, TRUE);
    }
error0:
    if(ACL_ENTRY_IS_INSTALLED(pe_lkup))
    {
        sys_usw_acl_buffer_malloc(lchip, pe_lkup, FALSE);
    }

    return ret;
}

STATIC int32
_sys_usw_acl_add_action_field(uint8 lchip, sys_acl_entry_t* pe_lkup, ctc_acl_field_action_t* action_field)
{
    uint8  is_half_ad = 0;
    uint8  is_install = 0;
    uint32 key_id = 0;
    uint32 act_id = 0;
    uint32 hw_index = 0;
    int32 ret = 0;
    ds_t   old_action = {0};
    sys_acl_aset_t* aset = NULL;

    if (CTC_ACL_FIELD_ACTION_LB_HASH_PROFILE == action_field->type)
    {
        action_field->type = CTC_ACL_FIELD_ACTION_LB_HASH_ECMP_PROFILE;
        ret = _sys_usw_acl_add_action_field(lchip, pe_lkup, action_field);
        action_field->type = CTC_ACL_FIELD_ACTION_LB_HASH_LAG_PROFILE;
        if(!ret && (ret = _sys_usw_acl_add_action_field(lchip, pe_lkup, action_field)))
        {
            action_field->type = CTC_ACL_FIELD_ACTION_LB_HASH_ECMP_PROFILE;
            _sys_usw_acl_remove_action_field(lchip, pe_lkup, action_field);
        }
        action_field->type = CTC_ACL_FIELD_ACTION_LB_HASH_PROFILE;
        return ret;
    }

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: action_field %u\n", action_field->type);

    CTC_ERROR_RETURN(_sys_usw_acl_get_aset(lchip, pe_lkup->aset_id, &aset));

    if((action_field->type < CTC_ACL_FIELD_ACTION_NUM) && !CTC_BMP_ISSET(aset->w, action_field->type))
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] aset not support \n");
        return CTC_E_INVALID_CONFIG;
    }

    is_install = ACL_ENTRY_IS_INSTALLED(pe_lkup);
    if(is_install)
    {
        /*1. rebuild buffer; if hash ad, copy buffer to new_buffer*/
        /*2. update action buffer(if hash, up new_buffer)*/
        SYS_ACL_GET_TBL_FUNC(lchip, pe_lkup, &key_id, &act_id, &hw_index);
        CTC_ERROR_RETURN(
            _sys_usw_acl_rebuild_buffer_from_hw(lchip, key_id, act_id, hw_index, pe_lkup));
        if(!ACL_ENTRY_IS_TCAM(pe_lkup))
        {
            sal_memcpy(old_action, pe_lkup->ua->buffer.action, sizeof(ds_t));
            SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_HASH_ENTRY, 1);
        }
        else
        {
            SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY, 1);
        }
    }

    if (ACL_ENTRY_IS_TCAM(pe_lkup))
    {
        if( CTC_ACL_KEY_INTERFACE == pe_lkup->key_type && !DRV_FROM_TMM(lchip))
        {
            is_half_ad = 1;
        }

        if (DRV_FROM_TMM(lchip) && CTC_EGRESS == pe_lkup->group->group_info.dir)
        {
              CTC_ERROR_GOTO(MCHIP_ACL(lchip)->add_egs_action_field(lchip, action_field, pe_lkup, 1), ret, error1);
        }
        else
        {
            switch(action_field->type)
            {
            case CTC_ACL_FIELD_ACTION_COLOR:
            case CTC_ACL_FIELD_ACTION_PRIORITY:
            case CTC_ACL_FIELD_ACTION_QOS_TABLE_MAP:
            case CTC_ACL_FIELD_ACTION_CANCEL_DISCARD:
            case CTC_ACL_FIELD_ACTION_DISCARD:
            case CTC_ACL_FIELD_ACTION_REDIRECT_PORT:
            case CTC_ACL_FIELD_ACTION_REDIRECT:
            case CTC_ACL_FIELD_ACTION_MICRO_FLOW_POLICER:
            case CTC_ACL_FIELD_ACTION_MACRO_FLOW_POLICER:
            case CTC_ACL_FIELD_ACTION_COS_HBWP_POLICER:
            case CTC_ACL_FIELD_ACTION_STATS:
            case CTC_ACL_FIELD_ACTION_CP_TO_CPU:
            case CTC_ACL_FIELD_ACTION_IPFIX:
            case CTC_ACL_FIELD_ACTION_IPFIX_HASH_SALT:
            case CTC_ACL_FIELD_ACTION_CANCEL_IPFIX:
            case CTC_ACL_FIELD_ACTION_CANCEL_IPFIX_LEARNING:
            case CTC_ACL_FIELD_ACTION_RANDOM_LOG:
            case CTC_ACL_FIELD_ACTION_XDATA:
                CTC_ERROR_GOTO(_sys_usw_acl_add_dsacl_field2(lchip, action_field, pe_lkup, is_half_ad, 1), ret, error1);
                break;
            default:
                CTC_ERROR_GOTO(_sys_usw_acl_add_dsacl_field(lchip, action_field, pe_lkup, is_half_ad, 1), ret, error1);
                break;
            }
        }
    }
    else
    {
        CTC_ERROR_GOTO(_sys_usw_acl_add_dsflow_field(lchip, action_field, (sys_acl_hash_entry_t*)pe_lkup, 1), ret, error0);
    }

    /*3. if entry is installed,
     *   for tcam, add action to hw, free buffer
     *   for hash, call add_hw, input old_action and new_action(to update spool)
    */
    if(is_install)
    {
        CTC_ERROR_GOTO(_sys_usw_acl_add_hw(lchip, pe_lkup, old_action), ret, error1);
    }

    return CTC_E_NONE;
error1:
    if(is_install && ACL_ENTRY_IS_TCAM(pe_lkup))
    {
        _sys_usw_acl_map_action_data(lchip, pe_lkup, TRUE);
    }
error0:
    if(is_install)
    {
        sys_usw_acl_buffer_malloc(lchip, pe_lkup, FALSE);
    }
    return ret;
}

int32
sys_usw_acl_add_action_field(uint8 lchip, uint32 entry_id, ctc_acl_field_action_t* action_field)
{
    int32 ret = 0;
    sys_acl_entry_t* pe_lkup = NULL;
    /*param check*/
    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(action_field);

    SYS_USW_ACL_LOCK(lchip);
    /*get entry and check*/
    _sys_usw_acl_get_entry_by_eid(lchip, entry_id, &pe_lkup);
    if (!pe_lkup)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Entry not exist \n");
        CTC_ERROR_RETURN(CTC_E_NOT_EXIST);
    }
    ret = _sys_usw_acl_add_action_field(lchip, pe_lkup, action_field);
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_remove_action_field(uint8 lchip, uint32 entry_id, ctc_acl_field_action_t* action_field)
{
    int32 ret = 0;
    sys_acl_entry_t* pe = NULL;
    /*param check*/
    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(action_field);

    SYS_USW_ACL_LOCK(lchip);
    _sys_usw_acl_get_entry_by_eid(lchip, entry_id, (void*)&pe);
    if (!pe)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Entry not exist \n");
        CTC_ERROR_RETURN(CTC_E_NOT_EXIST);
    }
    ret = _sys_usw_acl_remove_action_field(lchip, pe, action_field);
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

/*
 * add entry
 */
int32
sys_usw_acl_add_entry(uint8 lchip, uint32 group_id, ctc_acl_entry_t* p_ctc_entry)
{
    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_ctc_entry);

    SYS_ACL_CHECK_GROUP_ID(group_id);
    //CTC_MAX_VALUE_CHECK(p_ctc_entry->key_type, CTC_ACL_KEY_NUM - 1); need check when key_type > 255
    CTC_MAX_VALUE_CHECK(p_ctc_entry->hash_field_sel_id, SYS_ACL_HASH_SEL_PROFILE_MAX-1);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: group_id %u --eid %u -- key_type %u\n",  group_id, p_ctc_entry->entry_id, p_ctc_entry->key_type);

    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_add_entry(lchip, group_id, p_ctc_entry));

    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

/*
 * remove entry from software table
 */
int32
sys_usw_acl_remove_entry(uint8 lchip, uint32 entry_id)
{
    SYS_ACL_INIT_CHECK();

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: eid %u \n", entry_id);

    /* check raw entry */
    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_remove_entry(lchip, entry_id));

    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

/*
 * remove all entries from a group
 */
int32
sys_usw_acl_remove_all_entry(uint8 lchip, uint32 group_id)
{
    SYS_ACL_INIT_CHECK();
    SYS_ACL_CHECK_GROUP_ID(group_id);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: gid %u \n", group_id);

    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_remove_all_entry(lchip, group_id));

    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}
int32 _sys_usw_acl_upa_move(uint8 lchip, sys_acl_entry_t* pe, sys_acl_block_t* pb, uint32 tcam_idx_new)
{
    uint8   step         = 0;
    uint8   ad_step         = 0;
    uint8   part         = 0;
    uint8   part_num     = 0;
    uint8   key_size     = 0;
    uint8   global_pp_en = 0;
    uint32  old_key_id   = 0;
    uint32  old_act_id   = 0;
    uint32  new_key_id   = 0;
    uint32  new_act_id   = 0;
    uint32  old_hw_index = 0;
    uint32  new_hw_index = 0;
    uint32  old_offset_a = 0;
    uint32  temp_statsid = 0;
    sys_stats_acl_change_t stats_change = {0};
    uint8 pp_id = lchip - SYS_PP_BASE(lchip);
    drv_ioctl_param_t src_ioctl_param;
    drv_ioctl_param_t dst_ioctl_param;


    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    key_size = _sys_usw_acl_get_key_size(lchip, 1, pe, &step);
    CTC_MAX_VALUE_CHECK(tcam_idx_new, pb[0].fpab.entry_count-1);
    if(SYS_ACL_GROUP_IS_PRESEL(pe->group))
    {
        SYS_ACL_KEY_SIZE_TO_PART_NUM(key_size, part_num);
        SYS_ACL_KEY_SIZE_TO_STEP(key_size, ad_step);
        for(part=0; part < part_num; part++)
        {
            if(pb[part].fpab.entries[tcam_idx_new] != NULL)
            {
                return CTC_E_IN_USE;
            }
        }
    }
    else
    {
        uint32 temp_index = 0;
        uint8 temp_key_size = 0;
        part_num = 1;
        for(temp_key_size = key_size; temp_key_size < CTC_FPA_KEY_SIZE_NUM; temp_key_size++)
        {
            temp_index = (tcam_idx_new >> temp_key_size) << temp_key_size ;
            if(pb->fpab.entries[temp_index] && pb->fpab.entries[temp_index]->step == (1<<temp_key_size))
            {
                SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Acl tcam key index already used, line:%d\n", __LINE__);
                return CTC_E_IN_USE;
            }
        }
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_BLOCK, 1);


    SYS_ACL_GET_TBL_FUNC(lchip, pe, &old_key_id, &old_act_id, &old_hw_index);

    old_offset_a = pe->fpae.offset_a;
    pe->fpae.offset_a = tcam_idx_new;
    pe->fpae.priority = tcam_idx_new;
    for(part=0; part < part_num; part++)
    {
        pb[part].fpab.entries[tcam_idx_new] = pb[part].fpab.entries[old_offset_a];
        pb[part].fpab.entries[old_offset_a] = NULL;
    }
    SYS_ACL_GET_TBL_FUNC(lchip, pe, &new_key_id, &new_act_id, &new_hw_index);

    if (SYS_ACL_GROUP_IS_PRESEL(pe->group))
    {
        SYS_ACL_GET_STATS_ID(temp_statsid, pe);

        if(0 != temp_statsid && (new_key_id != old_key_id))
        {
            stats_change.cb = _sys_usw_acl_change_stats_ptr_cb;
            stats_change.user_data = (void*)pe;
            ACL_MAP_FLOW_STATS_BLOCK_ID(pe, pb, stats_change.new_block_id,key_size);
            stats_change.stats_id = temp_statsid;

            pe->fpae.offset_a = old_offset_a;
            sys_usw_flow_stats_change_acl_statsptr(lchip, &stats_change);
            pe->fpae.offset_a = tcam_idx_new;
        }

    }

    if (pe->ua != NULL && !pe->ua_type)
    {
        return CTC_E_NONE;
    }
    global_pp_en = SYS_ACL_IS_GLOBAL_PP_EN_LKUP(lchip, pe->group->group_info.dir, pe->group->group_info.block_id);
    /* move key and ad */
    src_ioctl_param.entry_len = part_num;
    src_ioctl_param.index = (DRV_IS_TMM(lchip) && CTC_EGRESS == pe->group->group_info.dir) ?old_hw_index/2 : old_hw_index;
    src_ioctl_param.op_bmp = (MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL) && !global_pp_en) ? (((1<<(pp_id/PP_NUM_PER_CORE)) << 6) | ((1<<(pp_id%PP_NUM_PER_CORE)) << 2)): 0xfc;
    src_ioctl_param.p_value = NULL;
    src_ioctl_param.tbl_id = old_key_id;
    src_ioctl_param.ad_index = SYS_ACL_MAP_DRV_AD_INDEX(old_hw_index, step);
    src_ioctl_param.ad_tbl_id = old_act_id+ad_step;

    dst_ioctl_param.entry_len = part_num;
    dst_ioctl_param.index = (DRV_IS_TMM(lchip) && CTC_EGRESS == pe->group->group_info.dir) ?new_hw_index/2 : new_hw_index;
    dst_ioctl_param.op_bmp = (MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL) && !global_pp_en) ? (((1<<(pp_id/PP_NUM_PER_CORE)) << 6) | ((1<<(pp_id%PP_NUM_PER_CORE)) << 2)): 0xfc;
    dst_ioctl_param.p_value = NULL;
    dst_ioctl_param.tbl_id = new_key_id;
    dst_ioctl_param.ad_index = SYS_ACL_MAP_DRV_AD_INDEX(new_hw_index, step);
    dst_ioctl_param.ad_tbl_id = new_act_id+ad_step;

    CTC_ERROR_RETURN(drv_ioctl_move_tcam(lchip, &src_ioctl_param, &dst_ioctl_param));

    return CTC_E_NONE;
}

/*
 * set priority of entry
 */
int32
_sys_usw_acl_set_entry_priority(uint8 lchip, uint32 entry_id, uint32 priority)
{
    sys_acl_entry_t* pe = NULL;
    sys_acl_group_t* pg = NULL;
    sys_acl_block_t* pb = NULL;
    uint8 key_size = 0;

    /* get sys entry */
    _sys_usw_acl_get_nodes_by_eid(lchip, entry_id, &pe, &pg, &pb);
    if(!pe)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }
    if (!pg)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Group not exist \n");
        return CTC_E_NOT_EXIST;
    }

    if (!ACL_ENTRY_IS_TCAM(pe)) /* hash entry */
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Hash entry has no priority \n");
        return CTC_E_INVALID_CONFIG;
    }

    /* tcam entry check pb */
    CTC_PTR_VALID_CHECK(pb);

    if(SYS_USW_ACL_UPA_EN(lchip, pe->group->group_info.dir))
    {
        return _sys_usw_acl_upa_move(lchip, pe, pb, priority);
    }
    else
    {
        key_size = _sys_usw_acl_get_key_size(lchip, 0, pe, NULL);
        return fpa_usw_set_entry_prio(p_usw_acl_master[lchip]->fpa, &pe->fpae, &pb->fpab, key_size, priority);
    }
    return CTC_E_NONE;
}

int32
sys_usw_acl_set_entry_priority(uint8 lchip, uint32 entry_id, uint32 priority)
{
    SYS_ACL_INIT_CHECK();
    SYS_ACL_CHECK_ENTRY_PRIO(priority);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: eid %u -- prio %u \n", entry_id, priority);


    SYS_USW_ACL_LOCK(lchip);
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_set_entry_priority(lchip, entry_id, priority));
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

/*
 * get multiple entries
 */
int32
sys_usw_acl_get_multi_entry(uint8 lchip, ctc_acl_query_t* query)
{
    uint32* p_array = NULL;
    uint32                entry_index = 0;
    uint32                entry_count = 0;
    sys_acl_group_t       * pg        = NULL;
    ctc_list_pointer_node_t* pe        = NULL;
    ctc_fpa_entry_t* fpe = NULL;
    uint16         block_idx = 0;
    uint16         start_idx = 0;
    uint16         end_idx = 0;
    uint8          step = 0;
    uint8          block_id = 0;
    uint8          is_program_acl = 0;
    sys_acl_block_t* pb = NULL;
    sys_acl_league_t* p_sys_league = NULL;

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(query);
    if(query->entry_size)
    {
        CTC_PTR_VALID_CHECK(query->entry_array);
    }

    SYS_ACL_DBG_FUNC();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "  %% PARAM: mode-%u lkuplevel-%u gid-%u entry_sz-%u\n", query->query_mode, query->lkup_level, query->group_id, query->entry_size);

    SYS_USW_ACL_LOCK(lchip);
    switch (query->query_mode)
    {
        case CTC_ACL_QUERY_MODE_GROUPID:
        {
            if (query->group_id >= CTC_ACL_GROUP_ID_MAX)
            {
                SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Invalid group id \n");
                SYS_USW_ACL_RETURN_UNLOCK(CTC_E_BADID);
            }
            /* get group node */
            _sys_usw_acl_get_group_by_gid(lchip, query->group_id, &pg);
            SYS_USW_ACL_CHECK_GROUP_UNEXIST_UNLOCK(pg);
            if (query->entry_size == 0)
            {
                query->entry_count = pg->entry_count;
            }
            else
            {
                p_array = query->entry_array;
                if (NULL == p_array)
                {
                    SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PTR);
                }
                if (query->entry_size > pg->entry_count)
                {
                    query->entry_size = pg->entry_count;
                }

                CTC_LIST_POINTER_LOOP(pe ,&(pg->entry_list))
                {
                    *p_array = ((sys_acl_entry_t*) pe)->fpae.entry_id;
                    p_array++;
                    entry_index++;
                    if (entry_index == query->entry_size)
                    {
                        break;
                    }
                }

                query->entry_count = query->entry_size;
            }
            break;
        }
        case CTC_ACL_QUERY_MODE_LKUP_LEVEL:
        {
            if ((query->lkup_level) > ((CTC_INGRESS == query->dir ? ACL_IGS_BLOCK_MAX_NUM-1: ACL_EGS_BLOCK_MAX_NUM-1)))
            {
                SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PARAM);
            }

            block_id = ((query->dir == CTC_INGRESS) ? query->lkup_level: query->lkup_level + ACL_IGS_BLOCK_MAX_NUM);
            pb = &SYS_ACL_BLOCK(lchip, block_id);
            p_sys_league = &(p_usw_acl_master[lchip]->league[block_id]);

            if (!p_sys_league->lkup_level_bitmap)
            {
                block_id = p_sys_league->merged_to;
                pb = &SYS_ACL_BLOCK(lchip, block_id);
                p_sys_league = &(p_usw_acl_master[lchip]->league[block_id]);
            }

            start_idx = p_sys_league->lkup_level_start[query->lkup_level];
            end_idx = p_sys_league->lkup_level_start[query->lkup_level] + p_sys_league->lkup_level_count[query->lkup_level];

            step  = 1;

            p_array = query->entry_array;
            if (query->entry_size != 0 && NULL == p_array)
            {
                SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PTR);
            }

            for (block_idx = start_idx; block_idx < end_idx; block_idx = block_idx + step)
            {

                if(SYS_USW_ACL_UPA_EN(lchip, query->dir))
                {
                    step = 1;
                }
                else if((block_idx >= pb->fpab.start_offset[CTC_FPA_KEY_SIZE_640]) && (pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_640]))      /*640 bit key*/
                {
                    step = 8;
                }
                else if(block_idx >= pb->fpab.start_offset[CTC_FPA_KEY_SIZE_320] && (pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_320]))   /*320 bit key*/
                {
                    step = 4;
                }
                else if(block_idx >= pb->fpab.start_offset[CTC_FPA_KEY_SIZE_160] && (pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_160]))   /*160 bit key*/
                {
                    step = 2;
                }
                else  /*80 bit key*/
                {
                    step = 1;
                }

                is_program_acl = query->dir == CTC_INGRESS && DRV_FROM_TMM(lchip);
                is_program_acl |= DRV_FROM_AT(lchip);
                step = is_program_acl? 1: step;

                fpe = pb->fpab.entries[block_idx];
                if (fpe)
                {
                    if (query->entry_size == 0)
                    {
                        entry_count++;
                    }
                    else
                    {
                        if (NULL == p_array)
                        {
                            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PTR);
                        }
                        *p_array++ = fpe->entry_id;
                        entry_count++;

                        if (entry_count == query->entry_size)
                        {
                            break;
                        }
                    }
                }
            }
            query->entry_count = entry_count;
            query->entry_num = p_sys_league->lkup_level_count[query->lkup_level];
            break;
        }
        default:
        {
            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PARAM);
        }
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_acl_copy_entry(uint8 lchip, ctc_acl_copy_entry_t* copy_entry)
{
    uint32 key_id = 0;
    uint32 act_id = 0;
    uint32 hw_index = 0;
    uint32 temp_id = 0;
    uint32 cpu_reason_id =0;
    sys_acl_entry_t * pe_src    = NULL;
    sys_acl_entry_t * pe_dst    = NULL;
    sys_acl_buffer_t* p_buffer  = NULL;
    sys_acl_block_t * pb_dst    = NULL;
    sys_acl_group_t * pg_dst    = NULL;
    sys_acl_vlan_edit_t* pv_get = NULL;
    sys_acl_flex_key_t*  p_fk   = NULL;
    sys_acl_field_range_t* p_range = NULL;
    uint8           block_id    = 0;
    uint32          block_index = 0;
    uint8           key_size    = 0;
    int32           ret         = 0;
    uint8           range_id    = 0;
    uint8           key_used_bitmap = 0;
    uint8           dir         = 0;
    uint8 global_pp_en = 0;
#if 1
    uint8           redirect_overlay_nh = 0;
    uint32 nhid = 0;
    uint32 ldp = 0;
    sys_acl_ldp_entry_t* pe_ldp_dst = NULL;
#endif
    sys_cpu_reason_info_t cpu_rason_info;

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(copy_entry);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_USW_ACL_LOCK(lchip);
    /* check src entry */
    _sys_usw_acl_get_entry_by_eid(lchip, copy_entry->src_entry_id, &pe_src);
    if (!pe_src)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Entry not exist \n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_EXIST);
    }

    if (!ACL_ENTRY_IS_TCAM(pe_src)) /* hash entry not support copy */
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Hash acl entry not support copy \n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_SUPPORT);
    }

    SYS_ACL_GET_STATS_ID(temp_id, pe_src);
    if (0 != temp_id && DRV_FROM_TMM(lchip))
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Stats not support copy \n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_SUPPORT);
    }

    /* check dst entry */
    _sys_usw_acl_get_entry_by_eid(lchip, copy_entry->dst_entry_id, &pe_dst);

    if (pe_dst)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Entry exist \n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_EXIST);
    }

    _sys_usw_acl_get_group_by_gid(lchip, copy_entry->dst_group_id, &pg_dst);
    SYS_USW_ACL_CHECK_GROUP_UNEXIST_UNLOCK(pg_dst);

    if (pg_dst->group_info.dir!=pe_src->group->group_info.dir)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Src group direction is not the same as dst group direction \n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_CONFIG);
    }

    dir = pe_src->group->group_info.dir;
    if(SYS_USW_ACL_UPA_EN(lchip, dir))
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_SUPPORT);
    }
    key_size = _sys_usw_acl_get_key_size(lchip, 0, pe_src, NULL);
    block_id = pg_dst->group_info.block_id;
    if(CTC_EGRESS == pg_dst->group_info.dir)
    {
        block_id += p_usw_acl_master[lchip]->igs_block_num;
    }
    pb_dst = &SYS_ACL_BLOCK(lchip, block_id);

    if(MCHIP_FEATURE_PP_EN(lchip, CTC_FEATURE_ACL))
    {
        uint32 src_bitmap = 0;
        uint32 dst_bitmap = 0;
        uint32 global_pp_en_bmp = 0;

        global_pp_en_bmp = p_usw_acl_master[SYS_PP_BASE(lchip)]->global_pp_en_bmp[pe_src->group->group_info.dir];
        src_bitmap = (global_pp_en_bmp >> pe_src->group->group_info.block_id) & ((1 << key_size)-1);
        dst_bitmap = (global_pp_en_bmp >> pg_dst->group_info.block_id) & ((1 << key_size)-1);
        if(src_bitmap != dst_bitmap)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Global acl bmp is conflict,line:%d\n",__LINE__);
            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_READY);
        }
    }

    _sys_usw_acl_get_key_size_bitmap(lchip, pb_dst, &key_used_bitmap, pg_dst->group_info.dir);
    if ((CTC_IS_BIT_SET(key_used_bitmap, CTC_FPA_KEY_SIZE_80) && (CTC_FPA_KEY_SIZE_80 != key_size)) || \
       (!CTC_IS_BIT_SET(key_used_bitmap, CTC_FPA_KEY_SIZE_80) && key_used_bitmap && (CTC_FPA_KEY_SIZE_80 == key_size)))
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Tcam key 80 can't be used with others!\n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_SUPPORT);
    }
    SYS_ACL_GET_NEXTHOP_ID(temp_id, pe_src);
    if (temp_id)
    {
        uint32 fwdptr = 0;
        sys_nh_info_dsnh_t nhinfo;
        sal_memset(&nhinfo, 0, sizeof(sys_nh_info_dsnh_t));

        CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo(lchip, temp_id, &nhinfo, 0), ret, cleanup_0);
        if(!nhinfo.ecmp_valid && pe_src->key_type != CTC_ACL_KEY_STK_HDR)
        {
            CTC_ERROR_GOTO(sys_usw_nh_get_dsfwd_offset(lchip, temp_id, &fwdptr, 0, CTC_FEATURE_ACL), ret, cleanup_0);
        }
#if 1
        if (DRV_FROM_TMM(lchip))
        {
            sys_acl_ldp_entry_t* pe_ldp_src = sys_usw_acl_get_ldp_entry_by_eid(lchip, pe_src->fpae.entry_id);
            if (pe_ldp_src)
            {
                redirect_overlay_nh = (pe_ldp_src->nhid_list_node.p_next || pe_ldp_src->nhid_list_node.p_prev);
                pe_ldp_dst = mem_malloc(MEM_ACL_MODULE,sizeof(sys_acl_ldp_entry_t));
                if (!pe_ldp_dst)
                {
                    ret = CTC_E_NO_MEMORY;
                    goto cleanup_0;
                }
                sal_memcpy(pe_ldp_dst, pe_ldp_src, sizeof(sys_acl_ldp_entry_t));
                pe_ldp_dst->entry_id = copy_entry->dst_entry_id;
                ctc_hash_insert(p_usw_acl_master[lchip]->ldp_entry, pe_ldp_dst);
            }
        }
#endif
    }

    MALLOC_ZERO(MEM_ACL_MODULE, pe_dst, sizeof(sys_acl_entry_t));
    if (!pe_dst)
    {
       ret = CTC_E_NO_MEMORY;
       goto cleanup_0;
    }
    sal_memcpy(pe_dst, pe_src, sizeof(sys_acl_entry_t));

    /*the pointer need re-assign value*/
    pe_dst->group = pg_dst;
    pe_dst->fpae.entry_id    = copy_entry->dst_entry_id;

    if (SYS_ACL_GROUP_IS_PRESEL(pe_src->group))
    {
        CTC_SET_FLAG(pg_dst->flag, SYS_ACL_GROUP_FLAG_PRESEL);
    }

    if (SYS_ACL_GROUP_IS_PRESEL(pg_dst)&&(NULL != MCHIP_ACL(lchip)->expand_link_block))
    {
        p_fk = SYS_ACL_GET_FK(lchip, pe_dst);

        if ((pb_dst->fpab.part_num>1) && (pb_dst->fpab.part != 0))
        {
            CTC_ERROR_GOTO(CTC_E_INVALID_CONFIG, ret, cleanup_pe);
        }

        CTC_ERROR_GOTO(MCHIP_ACL(lchip)->expand_link_block(lchip, pb_dst, p_fk, key_size), ret, cleanup_pe);
    }

    /* get block index, based on priority */
    if (SYS_ACL_GROUP_IS_PRESEL(pg_dst))
    {
        CTC_ERROR_GOTO(sys_usw_acl_alloc_offset(lchip, pb_dst, pe_dst, key_size), ret, cleanup_block);
    }
    else
    {
        CTC_ERROR_GOTO(fpa_usw_alloc_offset(p_usw_acl_master[lchip]->fpa, &(pb_dst->fpab), key_size,
                                            pe_src->fpae.priority, &block_index), ret, cleanup_block);
        pe_dst->fpae.offset_a = block_index;
        /* add to block */
        pb_dst->fpab.entries[block_index] = &pe_dst->fpae;
    }

    MALLOC_ZERO(MEM_ACL_MODULE, p_buffer, sizeof(sys_acl_buffer_t));
    if (!p_buffer)
    {
        ret = CTC_E_NO_MEMORY;
        goto cleanup_2;
    }
    pe_dst->ua = (void*)p_buffer;
    pe_dst->ua_type = 0;

    if(FPA_ENTRY_FLAG_INSTALLED == pe_src->fpae.flag)
    {
       SYS_ACL_GET_TBL_FUNC(lchip, pe_src, &key_id, &act_id, &hw_index);
       CTC_ERROR_GOTO(_sys_usw_acl_rebuild_buffer_from_hw(lchip, key_id, act_id, hw_index, pe_src), ret, cleanup_3);
    }
    sal_memcpy(p_buffer, pe_src->ua, sizeof(sys_acl_buffer_t));
    p_buffer->pa = NULL;
    if(FPA_ENTRY_FLAG_INSTALLED == pe_src->fpae.flag && pe_src->ua)
    {
        _sys_usw_acl_map_action_data(lchip, pe_src, TRUE);
        sys_usw_acl_buffer_malloc(lchip, pe_src, FALSE);
    }

    p_range = SYS_ACL_GROUP_IS_PRESEL(pg_dst)
              ? p_usw_acl_master[lchip]->field_range[1+pg_dst->group_info.dir]
              : p_usw_acl_master[lchip]->field_range[0];
    for (range_id=0; range_id<SYS_ACL_FIELD_RANGE_NUM; range_id++)
    {
        if (!CTC_IS_BIT_SET(pe_dst->un.g4.range_bitmap, range_id))
        {
            continue;
        }
        p_range->range[range_id].ref++;
    }

    if(pe_dst->ua && pe_dst->ua->buffer.ad.tcam.vlan_edit)
    {
        CTC_ERROR_GOTO(ctc_spool_add(p_usw_acl_master[lchip]->vlan_edit_spool, pe_dst->ua->buffer.ad.tcam.vlan_edit, NULL, &pv_get), ret, cleanup_3);
        pe_dst->ua->buffer.ad.tcam.vlan_edit = pv_get;
    }

    /*copy ether_type*/
    if(pe_src->un.g4.ether_type_valid && MCHIP_ACL(lchip)->add_compress_ether_type && SYS_ACL_GROUP_IS_PRESEL(pg_dst))
    {
        uint8  ether_type_index = pe_src->un.g4.ether_type_index;
        uint16 temp_ether_type = 0;

        temp_ether_type = sys_usw_acl_get_ether_type_by_index(lchip, pe_src, ether_type_index);
        global_pp_en = SYS_ACL_IS_GLOBAL_PP_EN_LKUP(lchip, pg_dst->group_info.dir, pg_dst->group_info.block_id);
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Acl] Copy entry add compress ether type: %X \n", temp_ether_type);
        CTC_ERROR_GOTO(MCHIP_ACL(lchip)->add_compress_ether_type(lchip, global_pp_en, pg_dst->group_info.dir, temp_ether_type, 0, NULL, &ether_type_index), ret, cleanup_4);
        pe_dst->un.g4.ether_type_index = ether_type_index;
        pe_dst->un.g4.ether_type_valid = 1;
    }
    else if(pe_src->un.g4.ether_type_valid)
    {
        uint8  ether_type_index = pe_src->un.g4.ether_type_index;
        uint16 temp_ether_type = 0;

        temp_ether_type = sys_usw_acl_get_ether_type_by_index(lchip, pe_src, ether_type_index);

        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Acl] Copy entry add compress ether type: %X \n", temp_ether_type);
        CTC_ERROR_GOTO(sys_usw_register_add_compress_ether_type(lchip, temp_ether_type, 0, NULL, &ether_type_index), ret, cleanup_4);
        pe_dst->un.g4.ether_type_index = ether_type_index;
        pe_dst->un.g4.ether_type_valid = 1;
    }

    sal_memset(&cpu_rason_info, 0, sizeof(sys_cpu_reason_info_t));
    SYS_ACL_GET_CPU_REASON_ID(cpu_reason_id, pe_src);
    if(cpu_reason_id)
    {
        cpu_rason_info.reason_id = cpu_reason_id;
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Acl] Copy entry add cpu reason id: %u \n", cpu_reason_id);
        CTC_ERROR_GOTO(sys_usw_cpu_reason_alloc_exception_index(lchip, pg_dst->group_info.dir, &cpu_rason_info), ret, cleanup_5);
    }

#if 1
{
    nhid = p_buffer->ad.tcam.nexthop_id;
    ldp = p_buffer->ad.tcam.ldp;

    if (redirect_overlay_nh)
    {
        CTC_ERROR_GOTO(sys_usw_add_ldp_node(lchip, p_usw_acl_master[lchip]->nhid_hash, pe_dst->ua->buffer.ad.tcam.nexthop_id, &pe_ldp_dst->nhid_list_node), ret, cleanup_6);
    }
    /*add ldp list*/
    if (nhid && ldp)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "add acl dsacl %d to ldp %d\n", pe_dst->fpae.offset_a, ldp);
        CTC_ERROR_GOTO(sys_usw_add_ldp_node(lchip, p_usw_acl_master[lchip]->ldp_hash, ldp, &pe_ldp_dst->ldp_node), ret, cleanup_6);
    }
}
#endif

    /* add to hash */
    if (!ctc_hash_insert(p_usw_acl_master[lchip]->entry, pe_dst))
    {
        ret = CTC_E_NO_MEMORY;
        goto cleanup_7;
    }
    /* add to group */
    ctc_list_pointer_insert_head(&(pg_dst->entry_list), &(pe_dst->head));
	/* mark flag */
    pe_dst->fpae.flag = FPA_ENTRY_FLAG_UNINSTALLED;
    /*build group info*/
    _sys_usw_acl_add_key_common_field_group_none(lchip, pe_dst);
    _sys_usw_acl_add_group_key_port_field(lchip, pe_dst->fpae.entry_id,pe_dst->group);

    /* set new priority */
    CTC_ERROR_GOTO(_sys_usw_acl_set_entry_priority(lchip, copy_entry->dst_entry_id, pe_src->fpae.priority),ret,cleanup_8);

    (pg_dst->entry_count)++;
    _sys_usw_acl_update_key_count(lchip, pe_dst, 1);
    _sys_usw_acl_update_aset_ref(lchip, pe_src->aset_id);
    if (SYS_ACL_GROUP_IS_PRESEL(pg_dst))
    {
        p_fk->entry_count[pg_dst->group_info.block_id]++;
    }
    else if (p_fk)
    {
        ACL_SHARE_PTR(p_fk,sys_acl_fixed_key_t)->entry_count++;
    }
    SYS_USW_ACL_UNLOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MASTER, 1);
    return CTC_E_NONE;

 cleanup_8:
     ctc_list_pointer_delete(&(pg_dst->entry_list), &(pe_dst->head));
     ctc_hash_remove(p_usw_acl_master[lchip]->entry, pe_dst);

 cleanup_7:
 #if 1
    /*remove ldp list*/
    if (nhid && ldp)
    {
        sys_usw_remove_ldp_node(lchip, p_usw_acl_master[lchip]->ldp_hash, ldp, &pe_ldp_dst->ldp_node);
    }
    if (redirect_overlay_nh)
    {
        sys_usw_remove_ldp_node(lchip, p_usw_acl_master[lchip]->nhid_hash, pe_dst->ua->buffer.ad.tcam.nexthop_id, &pe_ldp_dst->nhid_list_node);
    }

 cleanup_6:
#endif
    if (cpu_reason_id)
    {
        sys_usw_cpu_reason_free_exception_index(lchip, pg_dst->group_info.dir, &cpu_rason_info);
    }
 cleanup_5:
    if (pe_dst->un.g4.ether_type_valid && MCHIP_ACL(lchip)->remove_compress_ether_type && SYS_ACL_GROUP_IS_PRESEL(pg_dst))
    {
        MCHIP_ACL(lchip)->remove_compress_ether_type(lchip, global_pp_en, pg_dst->group_info.dir, pe_dst->un.g4.ether_type_index);
    }
    else if (pe_dst->un.g4.ether_type_valid)
    {
        CTC_ERROR_DUMP(sys_usw_register_remove_compress_ether_type(lchip, pe_dst->un.g4.ether_type_index));
    }
 cleanup_4:
    if (NULL != pe_dst->ua && NULL != pe_dst->ua->buffer.ad.tcam.vlan_edit)
    {
        ctc_spool_remove(p_usw_acl_master[lchip]->vlan_edit_spool, pe_dst->ua->buffer.ad.tcam.vlan_edit, NULL);
    }
 cleanup_3:
    sys_usw_acl_buffer_malloc(lchip, pe_dst, FALSE);
    CTC_ERROR_DUMP(_sys_usw_acl_remove_field_range(lchip, pg_dst->group_info.dir, ACL_RANGE_TYPE_NONE, SYS_ACL_GROUP_IS_PRESEL(pg_dst), &pe_dst->un.g4.range_bitmap));
 cleanup_2:
    fpa_usw_free_offset(&(pb_dst->fpab), pe_dst->fpae.offset_a);
 cleanup_block:
    if ((key_size > pb_dst->fpab.part_num) && (NULL != MCHIP_ACL(lchip)->compress_link_block))
    {
        MCHIP_ACL(lchip)->compress_link_block(lchip, pb_dst, p_fk);
    }
 cleanup_pe:
    if(pe_dst)
    {
        mem_free(pe_dst);
    }
 cleanup_0:
    if (pe_ldp_dst)
    {
        mem_free(pe_ldp_dst);
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_get_hash_field_sel(uint8 lchip, uint8 hash_key_type, uint8 field_sel_id,
                                                                        uint16 key_field_type, uint8* o_value )
{
    ds_t   ds_sel;
    uint8  value = 0;

    LCHIP_CHECK(lchip);
    CTC_PTR_VALID_CHECK(o_value);
    CTC_MAX_VALUE_CHECK(field_sel_id, 0xF);

    sal_memset(&ds_sel, 0, sizeof(ds_sel));
    if (CTC_ACL_KEY_HASH_MAC == hash_key_type)
    {
        CTC_ERROR_RETURN(_sys_usw_acl_get_field_sel(lchip, CTC_ACL_KEY_HASH_MAC, field_sel_id, &ds_sel));
        switch(key_field_type)
        {
        case CTC_FIELD_KEY_PORT:
                value = GetFlowL2HashFieldSelect(V, globalPortType_f, &ds_sel);
               if(ACL_HASH_GPORT_TYPE_GPORT == value)
               {
                    value = CTC_FIELD_PORT_TYPE_GPORT;
               }
               else if(ACL_HASH_GPORT_TYPE_LOGIC_PORT == value)
               {
                    value = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
               }
            break;
        case CTC_FIELD_KEY_METADATA:
            value = GetFlowL2HashFieldSelect(V, globalPortType_f, &ds_sel);
            if(ACL_HASH_GPORT_TYPE_METADATA != value)
            {
                value = 0;
            }
            break;

        case CTC_FIELD_KEY_ETHER_TYPE:
            value = GetFlowL2HashFieldSelect(V, etherTypeEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MAC_DA:
            value = GetFlowL2HashFieldSelect(V, macDaEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MAC_SA:
            value = GetFlowL2HashFieldSelect(V, macSaEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_STAG_VALID:
            value = GetFlowL2HashFieldSelect(V, vlanIdValidEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_SVLAN_ID:
        case CTC_FIELD_KEY_CVLAN_ID:
            value = GetFlowL2HashFieldSelect(V, vlanIdEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_STAG_COS:
            value = GetFlowL2HashFieldSelect(V, cosEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_STAG_CFI:
            value = GetFlowL2HashFieldSelect(V, cfiEn_f, &ds_sel);
            break;

        default:
            value = 0;
            break;
        }

    }
    else if (CTC_ACL_KEY_HASH_IPV4 == hash_key_type)
    {
        CTC_ERROR_RETURN(_sys_usw_acl_get_field_sel(lchip, CTC_ACL_KEY_HASH_IPV4, field_sel_id, &ds_sel));
        switch(key_field_type)
        {
        case CTC_FIELD_KEY_PORT:
            value = GetFlowL3Ipv4HashFieldSelect(V, globalPortType_f, &ds_sel);
           if(ACL_HASH_GPORT_TYPE_GPORT == value)
           {
                value = CTC_FIELD_PORT_TYPE_GPORT;
           }
           else if(ACL_HASH_GPORT_TYPE_LOGIC_PORT == value)
           {
                value = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
           }
        break;

        case CTC_FIELD_KEY_METADATA:
            value = GetFlowL3Ipv4HashFieldSelect(V, globalPortType_f, &ds_sel);
            if(ACL_HASH_GPORT_TYPE_METADATA != value)
            {
                value = 0;
            }
            break;

        case CTC_FIELD_KEY_IP_DSCP:
            value = GetFlowL3Ipv4HashFieldSelect(V, dscpEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IP_PRECEDENCE:
            value = GetFlowL3Ipv4HashFieldSelect(V, dscpEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IP_ECN:
            value = GetFlowL3Ipv4HashFieldSelect(V, ecnEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L4_TYPE:
            value = GetFlowL3Ipv4HashFieldSelect(V, layer4TypeEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L4_SRC_PORT:
            value = GetFlowL3Ipv4HashFieldSelect(V, l4SourcePortEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L4_DST_PORT:
            value = GetFlowL3Ipv4HashFieldSelect(V, l4DestPortEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IP_DA:
	        if (DRV_FROM_TMM(lchip))
	        {
	            value = GetFlowL3Ipv4HashFieldSelect(V, ipDaBitmap_f, &ds_sel)?1:0;
	        }
	        else
	        {
	            value = GetFlowL3Ipv4HashFieldSelect(V, ipDaEn_f, &ds_sel);
	        }
            break;

        case CTC_FIELD_KEY_IP_SA:
	        if (DRV_FROM_TMM(lchip))
	        {
	            value = GetFlowL3Ipv4HashFieldSelect(V, ipSaBitmap_f, &ds_sel)?1:0;
	        }
	        else
	        {
	            value = GetFlowL3Ipv4HashFieldSelect(V, ipSaEn_f, &ds_sel);
	        }
            break;

        case CTC_FIELD_KEY_ICMP_TYPE:
            value = GetFlowL3Ipv4HashFieldSelect(V, icmpTypeEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_ICMP_CODE:
            value = GetFlowL3Ipv4HashFieldSelect(V, icmpOpcodeEn_f, &ds_sel);
            break;
        case CTC_FIELD_KEY_VN_ID:
            value = GetFlowL3Ipv4HashFieldSelect(V, vxlanVniEn_f, &ds_sel);
            break;
        case CTC_FIELD_KEY_GRE_KEY:
            value = GetFlowL3Ipv4HashFieldSelect(V, greKeyEn_f, &ds_sel);
            break;
        default:
            value = 0;
            break;
        }

    }
    else if (CTC_ACL_KEY_HASH_MPLS == hash_key_type)
    {
        CTC_ERROR_RETURN(_sys_usw_acl_get_field_sel(lchip, CTC_ACL_KEY_HASH_MPLS, field_sel_id, &ds_sel));
        switch(key_field_type)
        {
        case CTC_FIELD_KEY_PORT:
            value = GetFlowL3MplsHashFieldSelect(V, globalPortType_f, &ds_sel);
           if(ACL_HASH_GPORT_TYPE_GPORT == value)
           {
                value = CTC_FIELD_PORT_TYPE_GPORT;
           }
           else if(ACL_HASH_GPORT_TYPE_LOGIC_PORT == value)
           {
                value = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
           }
        break;

        case CTC_FIELD_KEY_METADATA:
            value = GetFlowL3MplsHashFieldSelect(V, globalPortType_f, &ds_sel);
            if(ACL_HASH_GPORT_TYPE_METADATA != value)
            {
                value = 0;
            }
            break;

        case CTC_FIELD_KEY_LABEL_NUM:
            value = GetFlowL3MplsHashFieldSelect(V, labelNumEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_LABEL0:
            value = GetFlowL3MplsHashFieldSelect(V, mplsLabel0En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_LABEL1:
            value = GetFlowL3MplsHashFieldSelect(V, mplsLabel1En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_LABEL2:
            value = GetFlowL3MplsHashFieldSelect(V, mplsLabel2En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_EXP0:
            value = GetFlowL3MplsHashFieldSelect(V, mplsExp0En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_EXP1:
            value = GetFlowL3MplsHashFieldSelect(V, mplsExp1En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_EXP2:
            value = GetFlowL3MplsHashFieldSelect(V, mplsExp2En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_SBIT0:
            value = GetFlowL3MplsHashFieldSelect(V, mplsSbit0En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_SBIT1:
            value = GetFlowL3MplsHashFieldSelect(V, mplsSbit1En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_SBIT2:
            value = GetFlowL3MplsHashFieldSelect(V, mplsSbit2En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_TTL0:
            value = GetFlowL3MplsHashFieldSelect(V, mplsTtl0En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_TTL1:
            value = GetFlowL3MplsHashFieldSelect(V, mplsTtl1En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_TTL2:
            value = GetFlowL3MplsHashFieldSelect(V, mplsTtl2En_f, &ds_sel);
            break;

        default:
            value = 0;
            break;
        }

    }
    else if (CTC_ACL_KEY_HASH_IPV6 == hash_key_type)
    {
        CTC_ERROR_RETURN(_sys_usw_acl_get_field_sel(lchip, CTC_ACL_KEY_HASH_IPV6, field_sel_id, &ds_sel));
        switch(key_field_type)
        {
        case CTC_FIELD_KEY_PORT:
            value = GetFlowL3Ipv6HashFieldSelect(V, globalPortType_f, &ds_sel);
           if(ACL_HASH_GPORT_TYPE_GPORT == value)
           {
                value = CTC_FIELD_PORT_TYPE_GPORT;
           }
           else if(ACL_HASH_GPORT_TYPE_LOGIC_PORT == value)
           {
                value = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
           }
        break;

        case CTC_FIELD_KEY_METADATA:
            value = GetFlowL3Ipv6HashFieldSelect(V, globalPortType_f, &ds_sel);
            if(ACL_HASH_GPORT_TYPE_METADATA != value)
            {
                value = 0;
            }
            break;

        case CTC_FIELD_KEY_IP_DSCP:
            value = GetFlowL3Ipv6HashFieldSelect(V, dscpEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IP_PRECEDENCE:
            value = GetFlowL3Ipv6HashFieldSelect(V, dscpEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IP_ECN:
            value = GetFlowL3Ipv6HashFieldSelect(V, ecnEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L4_TYPE:
            value = GetFlowL3Ipv6HashFieldSelect(V, layer4TypeEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L4_SRC_PORT:
            value = GetFlowL3Ipv6HashFieldSelect(V, l4SourcePortEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L4_DST_PORT:
            value = GetFlowL3Ipv6HashFieldSelect(V, l4DestPortEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IPV6_DA:
	        if (DRV_FROM_TMM(lchip))
	        {
	            uint32 ip_mask[4];
	            GetFlowL3Ipv6HashFieldSelect(A, ipDaBitmap_f, &ds_sel, ip_mask);
				value = (ip_mask[0]|ip_mask[1]|ip_mask[2]|ip_mask[3])?1:0;
	        }
	        else
	        {
	            value = GetFlowL3Ipv6HashFieldSelect(V, ipDaEn_f, &ds_sel);
	        }
            break;

        case CTC_FIELD_KEY_IPV6_SA:
	        if (DRV_FROM_TMM(lchip))
	        {
	            uint32 ip_mask[4];
	            GetFlowL3Ipv6HashFieldSelect(A, ipSaBitmap_f, &ds_sel, ip_mask);
	            value = (ip_mask[0] | ip_mask[1] | ip_mask[2] | ip_mask[3])?1:0;
	        }
	        else
	        {
	            value = GetFlowL3Ipv6HashFieldSelect(V, ipSaEn_f, &ds_sel);
	        }
            break;

        case CTC_FIELD_KEY_ICMP_TYPE:
            value = GetFlowL3Ipv6HashFieldSelect(V, icmpTypeEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_ICMP_CODE:
            value = GetFlowL3Ipv6HashFieldSelect(V, icmpOpcodeEn_f, &ds_sel);
            break;
        case CTC_FIELD_KEY_VN_ID:
            value = GetFlowL3Ipv6HashFieldSelect(V, vxlanVniEn_f, &ds_sel);
            break;
        case CTC_FIELD_KEY_GRE_KEY:
            value = GetFlowL3Ipv6HashFieldSelect(V, greKeyEn_f, &ds_sel);
            break;
        default:
            value = 0;
            break;
        }

    }
    else if (CTC_ACL_KEY_HASH_L2_L3 == hash_key_type)
    {
        CTC_ERROR_RETURN(_sys_usw_acl_get_field_sel(lchip, CTC_ACL_KEY_HASH_L2_L3, field_sel_id, &ds_sel));
        switch(key_field_type)
        {
        case CTC_FIELD_KEY_PORT:
            value = GetFlowL2L3HashFieldSelect(V, globalPortType_f, &ds_sel);
           if(ACL_HASH_GPORT_TYPE_GPORT == value)
           {
                value = CTC_FIELD_PORT_TYPE_GPORT;
           }
           else if(ACL_HASH_GPORT_TYPE_LOGIC_PORT == value)
           {
                value = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
           }
        break;

        case CTC_FIELD_KEY_METADATA:
            value = GetFlowL2L3HashFieldSelect(V, globalPortType_f, &ds_sel);
            if(ACL_HASH_GPORT_TYPE_METADATA != value)
            {
                value = 0;
            }
            break;

        case CTC_FIELD_KEY_MAC_DA:
            value = GetFlowL2L3HashFieldSelect(V, macDaEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MAC_SA:
            value = GetFlowL2L3HashFieldSelect(V, macSaEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_STAG_VALID:
            value = GetFlowL2L3HashFieldSelect(V, svlanIdValidEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_SVLAN_ID:
            value = GetFlowL2L3HashFieldSelect(V, svlanIdEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_STAG_COS:
            value = GetFlowL2L3HashFieldSelect(V, stagCosEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_STAG_CFI:
            value = GetFlowL2L3HashFieldSelect(V, stagCfiEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_CTAG_VALID:
            value = GetFlowL2L3HashFieldSelect(V, cvlanIdValidEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_CVLAN_ID:
            value = GetFlowL2L3HashFieldSelect(V, cvlanIdEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_CTAG_COS:
            value = GetFlowL2L3HashFieldSelect(V, ctagCosEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_CTAG_CFI:
            value = GetFlowL2L3HashFieldSelect(V, ctagCfiEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L3_TYPE:
            value = GetFlowL2L3HashFieldSelect(V,  layer3TypeEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L4_TYPE:
            value = GetFlowL2L3HashFieldSelect(V, layer4TypeEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IP_DSCP:
            value = GetFlowL2L3HashFieldSelect(V, dscpEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IP_PRECEDENCE:
            value = GetFlowL2L3HashFieldSelect(V, dscpEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IP_ECN:
            value = GetFlowL2L3HashFieldSelect(V, ecnEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L4_SRC_PORT:
            value = GetFlowL2L3HashFieldSelect(V, l4SourcePortEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_L4_DST_PORT:
            value = GetFlowL2L3HashFieldSelect(V, l4DestPortEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_IP_DA:
	        if (DRV_FROM_TMM(lchip))
	        {
	            value = GetFlowL2L3HashFieldSelect(V, ipDaBitmap_f, &ds_sel)?1:0;
	        }
	        else
	        {
	            value = GetFlowL2L3HashFieldSelect(V, ipDaEn_f, &ds_sel);
	        }
            break;

        case CTC_FIELD_KEY_IP_SA:
	        if (DRV_FROM_TMM(lchip))
	        {
	            value = GetFlowL2L3HashFieldSelect(V, ipSaBitmap_f, &ds_sel)?1:0;
	        }
	        else
	        {
	            value = GetFlowL2L3HashFieldSelect(V, ipSaEn_f, &ds_sel);
	        }
            break;

        case CTC_FIELD_KEY_IP_TTL:
            value = GetFlowL2L3HashFieldSelect(V, ttlEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_ICMP_TYPE:
            value = GetFlowL2L3HashFieldSelect(V, icmpTypeEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_ICMP_CODE:
            value = GetFlowL2L3HashFieldSelect(V, icmpOpcodeEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_LABEL_NUM:
            value = GetFlowL2L3HashFieldSelect(V, labelNumEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_LABEL0:
            value = GetFlowL2L3HashFieldSelect(V, mplsLabel0En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_LABEL1:
            value = GetFlowL2L3HashFieldSelect(V, mplsLabel1En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_LABEL2:
            value = GetFlowL2L3HashFieldSelect(V, mplsLabel2En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_EXP0:
            value = GetFlowL2L3HashFieldSelect(V, mplsExp0En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_EXP1:
            value = GetFlowL2L3HashFieldSelect(V, mplsExp1En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_EXP2:
            value = GetFlowL2L3HashFieldSelect(V, mplsExp2En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_SBIT0:
            value = GetFlowL2L3HashFieldSelect(V, mplsSbit0En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_SBIT1:
            value = GetFlowL2L3HashFieldSelect(V, mplsSbit1En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_SBIT2:
            value = GetFlowL2L3HashFieldSelect(V, mplsSbit2En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_TTL0:
            value = GetFlowL2L3HashFieldSelect(V, mplsTtl0En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_TTL1:
            value = GetFlowL2L3HashFieldSelect(V, mplsTtl1En_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_MPLS_TTL2:
            value = GetFlowL2L3HashFieldSelect(V, mplsTtl2En_f, &ds_sel);
            break;
        case CTC_FIELD_KEY_VN_ID:
            value = GetFlowL2L3HashFieldSelect(V, vxlanVniEn_f, &ds_sel);
            break;
        case CTC_FIELD_KEY_GRE_KEY:
            value = GetFlowL2L3HashFieldSelect(V, greKeyEn_f, &ds_sel);
            break;
        default:
            value = 0;
            break;
        }

    }
    else if (CTC_ACL_KEY_HASH_NSH == hash_key_type)
    {
        CTC_ERROR_RETURN(_sys_usw_acl_get_field_sel(lchip, CTC_ACL_KEY_HASH_NSH, field_sel_id, &ds_sel));
        switch(key_field_type)
        {
        case CTC_FIELD_KEY_PORT:
                value = GetFlowNshHashFieldSelect(V, globalPortType_f, &ds_sel);
               if(ACL_HASH_GPORT_TYPE_GPORT == value)
               {
                    value = CTC_FIELD_PORT_TYPE_GPORT;
               }
               else if(ACL_HASH_GPORT_TYPE_LOGIC_PORT == value)
               {
                    value = CTC_FIELD_PORT_TYPE_LOGIC_PORT;
               }
            break;
        case CTC_FIELD_KEY_METADATA:
            value = GetFlowNshHashFieldSelect(V, globalPortType_f, &ds_sel);
            if(ACL_HASH_GPORT_TYPE_METADATA != value)
            {
                value = 0;
            }
            break;

        case CTC_FIELD_KEY_NSH_SPI:
            value = GetFlowNshHashFieldSelect(V, nshSphSpiEn_f, &ds_sel);
            break;

        case CTC_FIELD_KEY_NSH_SI:
            value = GetFlowNshHashFieldSelect(V, nshSphSiEn_f, &ds_sel);
            break;

        default:
            value = 0;
            break;
        }
    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    if(o_value)
    {
        *o_value = value;
    }

    return CTC_E_NONE;
}

int32
sys_usw_acl_map_ctc_to_sys_hash_key_type(uint8 key_type ,uint8 *o_key_type)
{
    uint8 key_type_tmp;
    switch(key_type)
    {
    case CTC_ACL_KEY_HASH_MAC:
        key_type_tmp = SYS_ACL_HASH_KEY_TYPE_MAC;
        break;
    case CTC_ACL_KEY_HASH_IPV4:
        key_type_tmp = SYS_ACL_HASH_KEY_TYPE_IPV4;
        break;
    case CTC_ACL_KEY_HASH_L2_L3:
        key_type_tmp = SYS_ACL_HASH_KEY_TYPE_L2_L3;
        break;
    case CTC_ACL_KEY_HASH_IPV6:
        key_type_tmp = SYS_ACL_HASH_KEY_TYPE_IPV6;
        break;
    case CTC_ACL_KEY_HASH_MPLS:
        key_type_tmp = SYS_ACL_HASH_KEY_TYPE_MPLS;
        break;
    case CTC_ACL_KEY_HASH_NSH:
        key_type_tmp = SYS_ACL_HASH_KEY_TYPE_NSH;
        break;
    default:
        return CTC_E_INVALID_PARAM;
       break;
    }
    *o_key_type = key_type_tmp;
    return CTC_E_NONE;
}

int32
sys_usw_acl_set_field_to_hash_field_sel(uint8 lchip, uint8 key_type, uint8 field_sel_id,
                                                           ctc_field_key_t* sel_field)
{
    uint8 sys_key_type = 0;
    int32 ret = 0;

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_ACL_INIT_CHECK();
    CTC_MAX_VALUE_CHECK(field_sel_id, SYS_ACL_HASH_SEL_PROFILE_MAX-1);
    CTC_PTR_VALID_CHECK(sel_field);

    CTC_ERROR_RETURN(sys_usw_acl_map_ctc_to_sys_hash_key_type(key_type,&sys_key_type));
    SYS_USW_ACL_LOCK(lchip);
    if(0 != p_usw_acl_master[lchip]->hash_sel_profile_count[sys_key_type][field_sel_id])
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Already in used \n");
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_IN_USE);
    }
    ret = _sys_usw_acl_check_hash_sel_field_union(lchip, sys_key_type, field_sel_id,sel_field);
    if(ret!= CTC_E_NONE )
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "check_hash_sel_field_union failed\n");
        SYS_USW_ACL_RETURN_UNLOCK(sel_field->data?ret:CTC_E_NONE);
    }

    switch(key_type)
    {
    case CTC_ACL_KEY_HASH_MAC:
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(
            _sys_usw_acl_add_hash_mac_sel_field(lchip, field_sel_id, sel_field, sel_field->data));
        break;

    case CTC_ACL_KEY_HASH_IPV4:
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(
            _sys_usw_acl_add_hash_ipv4_sel_field(lchip, field_sel_id, sel_field, sel_field->data));
        break;

    case CTC_ACL_KEY_HASH_IPV6:
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(
            _sys_usw_acl_add_hash_ipv6_sel_field(lchip, field_sel_id, sel_field, sel_field->data));
        break;

    case CTC_ACL_KEY_HASH_L2_L3:
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(
            _sys_usw_acl_add_hash_l2l3_sel_field(lchip, field_sel_id, sel_field, sel_field->data));
        break;

    case CTC_ACL_KEY_HASH_MPLS:
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(
            _sys_usw_acl_add_hash_mpls_sel_field(lchip, field_sel_id, sel_field, sel_field->data));
        break;

    case CTC_ACL_KEY_HASH_NSH:
        if (MCHIP_ACL(lchip)->add_hash_nsh_sel_field)
        {
            SYS_USW_ACL_ERROR_RETURN_UNLOCK(
            MCHIP_ACL(lchip)->add_hash_nsh_sel_field(lchip, field_sel_id, sel_field, sel_field->data));
        }
        else
        {
            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PARAM);
        }
        break;

    default:
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PARAM);
        break;
    }
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_set_hash_sel_field_union(lchip, sys_key_type, field_sel_id,sel_field, sel_field->data));
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_acl_ftm_acl_cb(uint8 lchip, sys_ftm_specs_info_t* specs_info)
{
    uint8 start = 0;
    uint8 end = 0;
    uint8 block_id = 0;

    CTC_PTR_VALID_CHECK(specs_info);
    SYS_ACL_INIT_CHECK();

    if(DRV_IS_DUET2(lchip))
    {
        specs_info->used_size = (p_usw_acl_master[lchip]->key_count[ACL_ALLOC_COUNT_TCAM_80])
                                + (p_usw_acl_master[lchip]->key_count[ACL_ALLOC_COUNT_TCAM_160]*2)
                                + (p_usw_acl_master[lchip]->key_count[ACL_ALLOC_COUNT_TCAM_320]*4)
                                + (p_usw_acl_master[lchip]->key_count[ACL_ALLOC_COUNT_TCAM_640]*8);
        return CTC_E_NONE;
    }

    if(specs_info->type == 0)
    {
        start = 0;
        end = p_usw_acl_master[lchip]->igs_block_num;
    }
    else
    {
        start = p_usw_acl_master[lchip]->igs_block_num;
        end = p_usw_acl_master[lchip]->igs_block_num+p_usw_acl_master[lchip]->egs_block_num;
    }

    for (block_id = start; block_id < end; block_id++)
    {
        specs_info->used_size +=  (p_usw_acl_master[lchip]->block[block_id].fpab.entry_count - p_usw_acl_master[lchip]->block[block_id].fpab.free_count);
    }
    if ((1 == specs_info->type) && (DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
    {
        specs_info->used_size = specs_info->used_size / 2;
    }

    return CTC_E_NONE;
}


int32
sys_usw_acl_ftm_acl_flow_cb(uint8 lchip, sys_ftm_specs_info_t* specs_info)
{
    CTC_PTR_VALID_CHECK(specs_info);
    SYS_ACL_INIT_CHECK();

    specs_info->used_size = (p_usw_acl_master[lchip]->key_count[ACL_ALLOC_COUNT_HASH]);

    return CTC_E_NONE;
}
int32
_sys_usw_acl_get_resource_by_priority(uint8 lchip, uint8 priority, uint8 dir, uint32*total, uint32* used)
{
    uint8          block_id = 0;
    sys_acl_block_t* pb = NULL;

    block_id = ((dir == CTC_INGRESS) ? priority: priority + ACL_IGS_BLOCK_MAX_NUM);
    pb = &p_usw_acl_master[lchip]->block[block_id];

    *total = pb->fpab.entry_count;
    *used = *total-pb->fpab.free_count;

    return CTC_E_NONE;

}
int32
sys_usw_acl_get_resource_by_priority(uint8 lchip, uint8 priority, uint8 dir, uint32*total, uint32* used)
{
    int32 ret = 0;

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(total);
    CTC_PTR_VALID_CHECK(used);

    CTC_MAX_VALUE_CHECK(dir, CTC_BOTH_DIRECTION - 1);
    SYS_ACL_CHECK_GROUP_PRIO(dir, priority);

    SYS_USW_ACL_LOCK(lchip);
    ret = _sys_usw_acl_get_resource_by_priority(lchip, priority, dir, total, used);

    SYS_USW_ACL_UNLOCK(lchip);
    return ret;

}
/*special process for mapping old API*/
int32 sys_usw_acl_add_port_field(uint8 lchip, uint32 entry_id, ctc_field_port_t port, ctc_field_port_t port_mask)
{
    ctc_field_key_t   key_field;
    sys_acl_entry_t   sys_entry;
    sys_acl_entry_t * pe_lkup = NULL;

    SYS_ACL_INIT_CHECK();

    sal_memset(&key_field, 0, sizeof(ctc_field_key_t));

    SYS_USW_ACL_LOCK(lchip);

    sal_memset(&sys_entry, 0, sizeof(sys_acl_entry_t));
    sys_entry.fpae.entry_id = entry_id;

    pe_lkup = ctc_hash_lookup(p_usw_acl_master[lchip]->entry, &sys_entry);
    if(!pe_lkup || !pe_lkup->group)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    if(CTC_ACL_GROUP_TYPE_NONE == pe_lkup->group->group_info.type
        && port.type != CTC_FIELD_PORT_TYPE_NONE)
    {
        key_field.type = CTC_FIELD_KEY_PORT;
        key_field.ext_data = &(port);
        key_field.ext_mask = &port_mask;

        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_operate_key_field(lchip, pe_lkup, &key_field, 1));
    }

    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_acl_add_remove_field_list(uint8 lchip, uint32 entry_id, void* p_field_list, uint32* p_field_cnt, uint8 is_key, uint8 is_add)
{
    uint8   error_cnt     = 0;
    int32   ret           = CTC_E_NONE;
    uint32  field_id      = 0;
    uint32  field_cnt     = 0;
    void*   p_field       = NULL;
    sys_acl_entry_t* pe_lkup = NULL;

    CTC_PTR_VALID_CHECK(p_field_list);
    CTC_PTR_VALID_CHECK(p_field_cnt);
    /*param check*/
    SYS_ACL_INIT_CHECK();

    SYS_USW_ACL_LOCK(lchip);
    /*get entry and check*/
    _sys_usw_acl_get_entry_by_eid(lchip, entry_id, &pe_lkup);
    if (!pe_lkup)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }

    field_cnt = *p_field_cnt;
    for (field_id=0; field_id<field_cnt; field_id+=1)
    {
        p_field = is_key? (void*)((ctc_field_key_t*)p_field_list + field_id): (void*)((ctc_acl_field_action_t*)p_field_list + field_id);
        CTC_PTR_VALID_CHECK(p_field);
        if (!is_key && !is_add)
        {
            ret = _sys_usw_acl_remove_action_field(lchip, pe_lkup, ((ctc_acl_field_action_t*)p_field));
        }
        else if (!is_key && is_add)
        {
            ret = _sys_usw_acl_add_action_field(lchip, pe_lkup, ((ctc_acl_field_action_t*)p_field));
        }
        else if (is_key && !is_add)
        {
            ret = _sys_usw_acl_operate_key_field(lchip, pe_lkup, ((ctc_field_key_t*)p_field), 0);
        }
        else
        {
            ret = _sys_usw_acl_operate_key_field(lchip, pe_lkup, ((ctc_field_key_t*)p_field), 1);
        }
        if (CTC_E_NONE != ret && is_add)
        {
            break;
        }
        else if (CTC_E_NONE != ret && !is_add)
        {
            error_cnt+=1;
        }
    }
    if (CTC_E_NONE != ret)
    {
        *p_field_cnt = is_add? field_id: field_id-error_cnt;
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}


#define _ACL_CID_PAIR_
int32
sys_usw_acl_add_cid_pair(uint8 lchip, ctc_acl_cid_pair_t* cid_pair)
{
    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(cid_pair);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_MAX_VALUE_CHECK(cid_pair->action_mode, CTC_ACL_CID_PAIR_ACTION_OVERWRITE_ACL);

    if(CTC_FLAG_ISSET(cid_pair->flag, CTC_ACL_CID_PAIR_FLAG_SRC_CID))
    {
        SYS_USW_CID_CHECK(lchip, cid_pair->src_cid);
    }
    if(CTC_FLAG_ISSET(cid_pair->flag, CTC_ACL_CID_PAIR_FLAG_DST_CID))
    {
        SYS_USW_CID_CHECK(lchip, cid_pair->dst_cid);
    }
    if((CTC_ACL_CID_PAIR_ACTION_OVERWRITE_ACL == cid_pair->action_mode)&&(cid_pair->acl_prop.acl_en))
    {
        CTC_MAX_VALUE_CHECK(cid_pair->acl_prop.acl_priority, ACL_IGS_BLOCK_MAX_NUM);
        SYS_USW_MAX_CLASS_ID_CHECK(cid_pair->acl_prop.class_id);
    }

    SYS_USW_ACL_LOCK(lchip);

    if(CTC_FLAG_ISSET(cid_pair->flag, CTC_ACL_CID_PAIR_FLAG_FLEX))    /*tcam*/
    {
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_add_tcam_cid_pair(lchip, cid_pair));
    }
    else      /*hash*/
    {
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_add_hash_cid_pair(lchip, cid_pair));
    }

    SYS_USW_ACL_UNLOCK(lchip);


    return CTC_E_NONE;
}

int32
sys_usw_acl_remove_cid_pair(uint8 lchip, ctc_acl_cid_pair_t* cid_pair)
{
    CTC_PTR_VALID_CHECK(cid_pair);
    SYS_ACL_INIT_CHECK();

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_USW_ACL_LOCK(lchip);

    if(CTC_FLAG_ISSET(cid_pair->flag, CTC_ACL_CID_PAIR_FLAG_FLEX))    /*tcam*/
    {
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_remove_tcam_cid_pair(lchip, cid_pair));
    }
    else   /*hash*/
    {
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_remove_hash_cid_pair(lchip, cid_pair));
    }
    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_acl_set_cid_priority(uint8 lchip, uint8 is_src_cid, uint8* p_prio_arry)
{
    uint8 prio_max_value = is_src_cid? 0x7: 0x3;

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_prio_arry);
    CTC_MAX_VALUE_CHECK(p_prio_arry[0], prio_max_value);
    CTC_MAX_VALUE_CHECK(p_prio_arry[1], prio_max_value);
    CTC_MAX_VALUE_CHECK(p_prio_arry[2], prio_max_value);
    CTC_MAX_VALUE_CHECK(p_prio_arry[3], prio_max_value);
    CTC_MAX_VALUE_CHECK(p_prio_arry[4], 0x7);
    CTC_MAX_VALUE_CHECK(p_prio_arry[5], 0x7);
    CTC_MAX_VALUE_CHECK(p_prio_arry[6], 0x7);

    CTC_ERROR_RETURN(_sys_usw_acl_set_cid_priority(lchip, is_src_cid, p_prio_arry));

    return CTC_E_NONE;
}
uint8
sys_usw_acl_map_ctc_to_sys_offset_type(uint8 lchip, uint8 offset_type)
{
    uint8 ret = DRV_ENUM(DRV_UDFPOSTYPE_NONE);
    switch(offset_type)
    {
        case CTC_ACL_UDF_OFFSET_L2 :
            ret = DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L2);
            break;
        case CTC_ACL_UDF_OFFSET_L3 :
            ret = DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L3);
            break;
        case CTC_ACL_UDF_OFFSET_L4 :
            ret = DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L4);
            break;
        case CTC_ACL_UDF_OFFSET_INNER_L2 :
            ret = DRV_ENUM(DRV_UDFPOSTYPE_INNER_L2);
            break;
        case CTC_ACL_UDF_OFFSET_INNER_L3 :
            ret = DRV_ENUM(DRV_UDFPOSTYPE_INNER_L3);
            break;
        case CTC_ACL_UDF_OFFSET_INNER_L4 :
            ret = DRV_ENUM(DRV_UDFPOSTYPE_INNER_L4);
            break;
        default :
            break;
    }
    return ret;
}

STATIC uint32
sys_usw_acl_map_sys_to_ctc_offset_type(uint8 lchip, uint8 offset_type)
{
    uint32 ret = CTC_ACL_UDF_TYPE_NONE;

    if(offset_type == DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L2))
    {
        ret = CTC_ACL_UDF_OFFSET_L2;
    }
    else if(offset_type == DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L3))
    {
        ret = CTC_ACL_UDF_OFFSET_L3;
    }
    else if(offset_type == DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L4))
    {
        ret = CTC_ACL_UDF_OFFSET_L4;
    }
    else if(offset_type == DRV_ENUM(DRV_UDFPOSTYPE_INNER_L2))
    {
        ret = CTC_ACL_UDF_OFFSET_INNER_L2;
    }
    else if(offset_type == DRV_ENUM(DRV_UDFPOSTYPE_INNER_L3))
    {
        ret = CTC_ACL_UDF_OFFSET_INNER_L3;
    }
    else if(offset_type == DRV_ENUM(DRV_UDFPOSTYPE_INNER_L4))
    {
        ret = CTC_ACL_UDF_OFFSET_INNER_L4;
    }
    return ret;
}

int32
sys_usw_acl_udf_map_sys_to_ctc(uint8 lchip, sys_acl_udf_entry_t* p_sys_udf_entry, ctc_acl_classify_udf_t*  p_udf_entry)
{
    ParserUdfCamResult_m udf_rst[SYS_UDF_CAM_TYPE_NUM];
    ParserUdfCam_m udf_cam;
    IpeUdfIpfixCtl_m   udf_ipfix_ctl;
    uint32 cmd = 0;
    uint8 offset_type = 0;
    uint8 offset_type_valid = 1;/* not arrary*/
    uint8 offset_len = 0;
    uint8 loop_i = 0;
    uint8 cam_type = 0;
    uint8* p_udf = NULL;
    uint32 hw_udf[4] = {0};
    uint8  step = 1;

    CTC_PTR_VALID_CHECK(p_sys_udf_entry);
    CTC_PTR_VALID_CHECK(p_udf_entry);
    cam_type = p_sys_udf_entry->is_sudf? SYS_UDF_CAM_TYPE_ACL: SYS_UDF_CAM_TYPE_FIB;

    sal_memset(udf_rst, 0, SYS_UDF_CAM_TYPE_NUM * sizeof(ParserUdfCamResult_m));
    sal_memset(&udf_cam, 0, sizeof(ParserUdfCam_m));

    p_udf_entry->udf_id = p_sys_udf_entry->udf_id;
    p_udf_entry->udf_ad_id = p_sys_udf_entry->is_sudf?
        (1+ p_sys_udf_entry->udf_hit_index-MCHIP_CAP(SYS_CAP_ACL_SUDF_AD_ID_MIN)):p_sys_udf_entry->udf_hit_index;
    p_udf_entry->offset_num = ((!p_sys_udf_entry->granularity) && (DRV_FROM_TMM(lchip))) ? p_sys_udf_entry->udf_offset_num/2 : p_sys_udf_entry->udf_offset_num;
    if (p_sys_udf_entry->scl_key_valid)
    {
        p_udf_entry->scl_key->offset_num = (!p_sys_udf_entry->granularity && DRV_FROM_TMM(lchip)) ? p_sys_udf_entry->scl_offset_num/2 : p_sys_udf_entry->scl_offset_num;
    }
    else
    {
        p_udf_entry->scl_key = NULL;
    }
    p_udf_entry->priority = SYS_ACL_UDF_IDX_2_PRI(lchip,p_sys_udf_entry);
    p_udf_entry->granularity = p_sys_udf_entry->granularity;
    p_udf_entry->sudf_en = p_sys_udf_entry->is_sudf;

    if (!p_sys_udf_entry->granularity && DRV_FROM_TMM(lchip))
    {
        step = 2;
    }
    offset_len = p_sys_udf_entry->granularity ? 2:4;
    CTC_ERROR_RETURN(sys_usw_parser_io_get_parser_udf_cam_result(lchip, udf_rst, p_sys_udf_entry->key_index,p_sys_udf_entry->is_sudf,p_usw_acl_master[lchip]->udf_mode));
    p_udf_entry->tcp_option_en = GetParserUdfCamResult(V, skipTcpOption_f, &udf_rst[cam_type]);
    p_udf_entry->skip_vlan =       GetParserUdfCamResult(V, skipVlanTag_f, &udf_rst[cam_type]);
    GetParserUdfCamResult(A, udfMask_f, &udf_rst[cam_type], hw_udf);
    p_udf = &p_udf_entry->mask[0];
    SYS_USW_SET_USR_UDF(p_udf_entry->granularity, p_udf, hw_udf);
    if (p_udf_entry->scl_key)
    {
        GetParserUdfCamResult(A, udfMask_f, &udf_rst[SYS_UDF_CAM_TYPE_SCL], hw_udf);
        p_udf = &p_udf_entry->scl_key->mask[0];
        SYS_USW_SET_USR_UDF(p_udf_entry->granularity, p_udf, hw_udf);
    }
    if(GetParserUdfCamResult(V, aclUdfEn_f, &udf_rst[cam_type]))
    {
        CTC_SET_FLAG(p_udf_entry->flag,CTC_ACL_CLASSIFY_UDF_ACL_XDATA);
    }
    /* First: StartPosType */
    if (DRV_FLD_IS_EXISIT(ParserUdfCamResult_t, ParserUdfCamResult_udfStartPosType_f)) /* D2 */
    {
        offset_type = GetParserUdfCamResult(V, udfStartPosType_f, &udf_rst[cam_type]);
        p_udf_entry->offset_type = sys_usw_acl_map_sys_to_ctc_offset_type(lchip, offset_type);
    }
    else
    {
        for (loop_i = 0; loop_i < p_udf_entry->offset_num; loop_i ++)
        {
            offset_type = GetParserUdfCamResult(V, udfStartPosType0_f+loop_i*step + step/2, &udf_rst[cam_type]);
            p_udf_entry->offset_type_array[loop_i] = sys_usw_acl_map_sys_to_ctc_offset_type(lchip, offset_type);
            if (loop_i > 0 && p_udf_entry->offset_type_array[loop_i] != p_udf_entry->offset_type_array[loop_i-1])
            {
                offset_type_valid = 0;
            }
        }
        if (offset_type_valid)
        {
            p_udf_entry->offset_type = p_udf_entry->offset_type_array[0];
        }
    }
    if (p_udf_entry->scl_key)
    {
        offset_type_valid = 1;
        for (loop_i = 0; loop_i < p_udf_entry->scl_key->offset_num; loop_i ++)
        {
            offset_type = GetParserUdfCamResult(V, udfStartPosType0_f+loop_i*step + step/2, &udf_rst[SYS_UDF_CAM_TYPE_SCL]);
            p_udf_entry->scl_key->offset_type_array[loop_i] = sys_usw_acl_map_sys_to_ctc_offset_type(lchip, offset_type);
            if (loop_i > 0 && p_udf_entry->scl_key->offset_type_array[loop_i] != p_udf_entry->scl_key->offset_type_array[loop_i-1])
            {
                offset_type_valid = 0;
            }
        }
        if (offset_type_valid)
        {
            p_udf_entry->scl_key->offset_type = p_udf_entry->scl_key->offset_type_array[0];
        }
    }

    /* Second: offset */
    for (loop_i = 0; loop_i < p_udf_entry->offset_num; loop_i ++)
    {
        p_udf_entry->offset[loop_i] = GetParserUdfCamResult(V, udfEntryOffset0_f + loop_i*step + step/2, &udf_rst[cam_type]) * offset_len;
        if (!p_sys_udf_entry->granularity && DRV_FROM_TMM(lchip))
        {
            p_udf_entry->offset[loop_i] = p_udf_entry->offset[loop_i]/MCHIP_CAP(SYS_CAP_ACL_UDF_OFFSET_BYTE_LEN);
        }
    }
    if (p_udf_entry->scl_key)
    {
        for (loop_i = 0; loop_i < p_udf_entry->scl_key->offset_num; loop_i ++)
        {
            p_udf_entry->scl_key->offset[loop_i] = GetParserUdfCamResult(V, udfEntryOffset0_f + loop_i *step + step/2, &udf_rst[SYS_UDF_CAM_TYPE_SCL]) * offset_len;
            if (!p_sys_udf_entry->granularity && DRV_FROM_TMM(lchip))
            {
                p_udf_entry->scl_key->offset[loop_i] = p_udf_entry->scl_key->offset[loop_i]/MCHIP_CAP(SYS_CAP_ACL_UDF_OFFSET_BYTE_LEN);
            }
        }
    }

    if(DRV_FROM_TMM(lchip))
    {
        cmd = DRV_IOR(IpeUdfIpfixCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &udf_ipfix_ctl));
        if(GetIpeUdfIpfixCtl(V, udfIpfixMatchIndexA0_f, &udf_ipfix_ctl) && (GetIpeUdfIpfixCtl(V, udfIpfixMatchIndexA0_f, &udf_ipfix_ctl) == p_sys_udf_entry->udf_hit_index))
        {
            p_udf_entry->ipfix_en = GetIpeUdfIpfixCtl(V, udfIpfixMatchIndexA0Valid_f , &udf_ipfix_ctl);
        }
        p_udf_entry->valid = p_sys_udf_entry->is_installed;
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_parser_io_get_parser_udf_cam(lchip, &udf_cam, p_sys_udf_entry->key_index));
        p_udf_entry->valid = GetParserUdfCam(V, entryValid_f, &udf_cam);
    }
    return CTC_E_NONE;
}

int32
sys_usw_acl_get_udf_info(uint8 lchip,  uint32 udf_id, sys_acl_udf_info_t* p_udf_info)
{
    sys_acl_udf_entry_t* p_udf_entry = NULL;
    CTC_PTR_VALID_CHECK(p_udf_info);

    SYS_USW_ACL_LOCK(lchip);
    _sys_usw_acl_get_udf_info(lchip,  udf_id, &p_udf_entry);
    if(NULL == p_udf_entry)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }
    p_udf_info->is_sudf = p_udf_entry->is_sudf;
    p_udf_info->key_index = p_udf_entry->key_index;
    p_udf_info->udf_offset_num = p_udf_entry->udf_offset_num;
    p_udf_info->udf_hit_index = p_udf_entry->udf_hit_index;
    p_udf_info->scl_offset_num = p_udf_entry->scl_offset_num;
    p_udf_info->key_index_used = p_udf_entry->key_index_used;
    p_udf_info->granularity = p_udf_entry->granularity;
    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_acl_get_udf_info_by_ad_id(uint8 lchip, uint32 udf_ad_id, sys_acl_udf_info_t* p_udf_info)
{
    sys_acl_udf_entry_t* p_udf_entry = NULL;
    CTC_PTR_VALID_CHECK(p_udf_info);
    SYS_USW_ACL_LOCK(lchip);
    _sys_usw_acl_get_udf_entry_by_ad_id(lchip, udf_ad_id, &p_udf_entry);
    if(NULL == p_udf_entry)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }
    p_udf_info->granularity = p_udf_entry->granularity;
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

#define _ACL_UDF_ENTRY_
int32
_sys_usw_acl_get_udf_entry_by_priority_cb(void* bucket_data, void* user_data)
{
    uint16 udf_priority = 0;
    uint16 udf_priority_used = 0;
    sys_acl_udf_entry_t* p_sys_udf_entry = NULL;
    uint8 lchip = 0;

    p_sys_udf_entry = (sys_acl_udf_entry_t*)bucket_data;
    lchip   = ((sys_acl_traverse_data_t*)user_data)->value0;
    udf_priority = *(uint16*)(((sys_acl_traverse_data_t*)user_data)->data0);

    udf_priority_used = SYS_ACL_UDF_IDX_2_PRI(lchip, p_sys_udf_entry);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "udf entry priority: %u;  key index: %u\n", udf_priority_used, p_sys_udf_entry->key_index);

    if(udf_priority_used == udf_priority)
    {
        ((sys_acl_traverse_data_t*)user_data)->data1 = p_sys_udf_entry;
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "udf entry priority: %u\n", udf_priority);
    }

    return CTC_E_NONE;
}

int32
_sys_usw_acl_get_udf_entry_by_priority(uint8 lchip, uint16 priority, sys_acl_udf_entry_t** o_pe_udf)
{
    sys_acl_traverse_data_t  user_data;

    sal_memset(&user_data, 0, sizeof(sys_acl_traverse_data_t));

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    user_data.data0 = (void*)&priority;
    user_data.data1 = NULL;
    user_data.value0 = lchip;
    CTC_ERROR_RETURN(ctc_hash_traverse(p_usw_acl_master[lchip]->udf_entry, _sys_usw_acl_get_udf_entry_by_priority_cb, (void*) (&user_data)));
    *o_pe_udf = (sys_acl_udf_entry_t*)user_data.data1;

    return CTC_E_NONE;
}

int32
sys_usw_acl_get_udf_entry(uint8 lchip, ctc_acl_classify_udf_t* p_udf_entry)
{
    sys_acl_udf_entry_t    *p_sys_udf_entry =NULL;
    sys_acl_traverse_data_t  user_data;

    sal_memset(&user_data, 0, sizeof(sys_acl_traverse_data_t));

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_udf_entry);
    /* priority 511(index 0) reserved, priority is only use for normal udf */
    CTC_MAX_VALUE_CHECK(p_udf_entry->priority, MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM) - 1);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "get_udf_entry, query_type:%d,udf_id: %u,priority:%d \n", p_udf_entry->query_type, p_udf_entry->udf_id, p_udf_entry->priority);

    if(p_usw_acl_master[lchip]->udf_fpa_en && p_udf_entry->query_type)
    {
        return CTC_E_NOT_SUPPORT;
    }
    SYS_USW_ACL_LOCK(lchip);
    if (!p_udf_entry->query_type) /* by udf_id */
    {
        _sys_usw_acl_get_udf_info(lchip,  p_udf_entry->udf_id, &p_sys_udf_entry);
    }
    else /* by priority */
    {
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_get_udf_entry_by_priority(lchip, p_udf_entry->priority, &p_sys_udf_entry));
    }
    if (!p_sys_udf_entry || !p_sys_udf_entry->key_index_used)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_EXIST);
    }

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(sys_usw_acl_udf_map_sys_to_ctc(lchip, p_sys_udf_entry, p_udf_entry));

    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_acl_get_udf_hit_index(uint8 lchip,  uint32 udf_id, uint16* udf_hit_index)
{
    sys_acl_udf_entry_t *p_udf_entry;
    SYS_ACL_INIT_CHECK();

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  %% PARAM: udf_id %u \n", udf_id);
    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_get_udf_info(lchip, udf_id, &p_udf_entry));
    if(p_udf_entry == NULL)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    *udf_hit_index = p_udf_entry->udf_hit_index;

    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
_sys_usw_acl_get_udf_id_by_hit_index(void* bucket_data, void* user_data)
{
    sys_acl_traverse_data_t* p_traverse_data = user_data;
    uint16 udf_hit_index = *(uint16*)p_traverse_data->data0;
    sys_acl_udf_entry_t* p_sys_udf_entry = (sys_acl_udf_entry_t*)bucket_data;

    if (!p_sys_udf_entry || (p_sys_udf_entry->udf_hit_index != udf_hit_index))
    {
        return CTC_E_NONE;
    }

    *(uint32*)p_traverse_data->data1 = p_sys_udf_entry->udf_id;
    return CTC_E_EXIST;
}

int32 sys_usw_acl_get_udf_id(uint8 lchip, uint16 udf_hit_index, uint32* p_udf_id)
{
    sys_acl_traverse_data_t  user_data;
    sal_memset(&user_data, 0, sizeof(sys_acl_traverse_data_t));
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    user_data.data0 = (void*)&udf_hit_index;
    user_data.data1 = (void*)p_udf_id;
    user_data.value0 = lchip;
    SYS_USW_ACL_LOCK(lchip);
    ctc_hash_traverse(p_usw_acl_master[lchip]->udf_entry, _sys_usw_acl_get_udf_id_by_hit_index, (void*)(&user_data));
    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_acl_resv_udf_for_srv6(uint8 lchip, uint32* udf_index_base, uint8 sid_format, uint8 usid_prefix_len, uint8 gsid_prefix_len, uint8 is_deinit)
{
#define SYS_SRH_OFFSET (40)       /*srh from l3offset*/
#define SYS_SID_OFFSET (40 + 8)  /*ipv6 header len + 8 from l3offset*/
#define SYS_DIP_OFFSET (24)       /*ipv6 da offset from l3offset*/
#define SYS_SRV6_RSV_UDF_FOR_SID 8
#define SYS_SRV6_RSV_UDF_FOR_USID 1
#define SYS_SRV6_RSV_UDF_FOR_GSID 12
#define SYS_SRV6_USID_PREFIX_LEN_16 16
#define SYS_SRV6_USID_PREFIX_LEN_32 32
#define SYS_SRV6_USID_PREFIX_LEN_48 48
#define SYS_SRV6_USID_USID_LEN      16

#define SYS_SRV6_GSID_GSID_LEN      32

#define SYS_SRV6_SID_FORMAT_NORMAL 0x1
#define SYS_SRV6_SID_FORMAT_USID 0x2
#define SYS_SRV6_SID_FORMAT_GSID 0x4
    sys_usw_opf_t   opf;
    ctc_acl_classify_udf_t udf_entry;
    ctc_field_key_t key_field;
    uint32 cmd = 0;
    uint8 i = 0, j = 0;
    uint32 udfMask[4];/*128bits*/
    ParserUdfCamResult_m result;
    uint32 udf_hit_index = 0;
    uint8 udf_num = 0;
    uint8 sid_num = 0;

    /* calculate reserved udf num */
    if (CTC_FLAG_ISSET(sid_format, SYS_SRV6_SID_FORMAT_NORMAL))
    {
        udf_num = udf_num + SYS_SRV6_RSV_UDF_FOR_SID;
        sid_num = SYS_SRV6_RSV_UDF_FOR_SID;
    }
    if (CTC_FLAG_ISSET(sid_format, SYS_SRV6_SID_FORMAT_USID))
    {
        udf_num = udf_num + SYS_SRV6_RSV_UDF_FOR_USID;
    }
    else if (CTC_FLAG_ISSET(sid_format, SYS_SRV6_SID_FORMAT_GSID))
    {
        udf_num = udf_num + SYS_SRV6_RSV_UDF_FOR_GSID;
    }

    if (is_deinit)
    {
        udf_entry.udf_id = SYS_ACL_UDE_RSV_ID(SYS_ACL_UDF_RSV_SRV6);
        sys_usw_acl_remove_udf_entry(lchip, &udf_entry);

        sal_memset(&opf, 0, sizeof(opf));
        opf.pool_type  = p_usw_acl_master[lchip]->opf_type_udf;
        opf.pool_index = SYS_USW_ACL_SUDF_AD_INDEX;
        opf.multiple = 0;
        sys_usw_opf_free_offset(lchip, &opf, udf_num, *udf_index_base);

        cmd = DRV_IOR(ParserUdfCamResult0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, *udf_index_base , DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &result));
        udf_hit_index = GetParserUdfCamResult(V, udfMappedIndex_f, &result);
        opf.pool_index = SYS_USW_ACL_UDF_MAPPED_INDEX1;
        opf.multiple = 0;
        sys_usw_opf_free_offset(lchip, &opf, 1, udf_hit_index);
        return CTC_E_NONE;
    }

    /* 1. UDF key to extract SRH, used for sr process in scl. ParserUdfCamResult2_t */
    sal_memset(&udf_entry, 0, sizeof(ctc_acl_classify_udf_t));
    sal_memset(udfMask, 0xFF, sizeof(udfMask));
    udf_entry.skip_vlan = 1;
    udf_entry.granularity = 1;
    udf_entry.offset_num = 3;
    udf_entry.offset_type_array[0] = CTC_ACL_UDF_OFFSET_L3;
    udf_entry.offset_type_array[1] = CTC_ACL_UDF_OFFSET_L3;
    udf_entry.offset_type_array[2] = CTC_ACL_UDF_OFFSET_L3;
    udf_entry.offset[0] = SYS_SRH_OFFSET + 2;
    udf_entry.offset[1] = SYS_SRH_OFFSET;
    udf_entry.offset[2] = SYS_DIP_OFFSET + 14; /* SI Behand Gsid : 12; End of IPDA : 14 */
    udf_entry.udf_id = SYS_ACL_UDE_RSV_ID(SYS_ACL_UDF_RSV_SRV6);
    udf_entry.priority = SYS_ACL_UDE_RSV_PRI(SYS_ACL_UDF_RSV_SRV6);
    sal_memcpy((uint8*)(udf_entry.mask), (uint8*)udfMask, sizeof(udfMask));
    CTC_ERROR_RETURN(sys_usw_acl_add_udf_entry(lchip, &udf_entry));
    key_field.type = CTC_FIELD_KEY_L3_TYPE;
    key_field.data = CTC_PARSER_L3_TYPE_IPV6;
    key_field.mask = 0xF;
    CTC_ERROR_RETURN(sys_usw_acl_add_udf_entry_key_field(lchip, SYS_ACL_UDE_RSV_ID(SYS_ACL_UDF_RSV_SRV6), &key_field));
    key_field.type = CTC_FIELD_KEY_METADATA;
    key_field.data = (4 << 8) ;/* Routing Type = 4 with defferent SL values*/
    key_field.mask = 0xFF00;
    CTC_ERROR_RETURN(sys_usw_acl_add_udf_entry_key_field(lchip, SYS_ACL_UDE_RSV_ID(SYS_ACL_UDF_RSV_SRV6), &key_field));
    key_field.type = CTC_FIELD_KEY_L3_EXT_TYPE;
    key_field.data = SYS_PARSER_L3_EXT_TYPE_SRV6 ;
    key_field.mask = 0xF;
    CTC_ERROR_RETURN(sys_usw_acl_add_udf_entry_key_field(lchip, SYS_ACL_UDE_RSV_ID(SYS_ACL_UDF_RSV_SRV6), &key_field));
    key_field.type = CTC_FIELD_KEY_UDF_ENTRY_VALID;
    key_field.data = 1;
    key_field.mask = 1;
    CTC_ERROR_RETURN(sys_usw_acl_add_udf_entry_key_field(lchip, SYS_ACL_UDE_RSV_ID(SYS_ACL_UDF_RSV_SRV6), &key_field));

    /* 2. Flow UDF for fib lookup. ParserUdfCamResult1_t */
    /* 2.1 rsv hit index */
    sal_memset(&opf, 0, sizeof(opf));
    opf.pool_type  = p_usw_acl_master[lchip]->opf_type_udf;
    opf.pool_index = SYS_USW_ACL_UDF_MAPPED_INDEX1;
    CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, 1, &udf_hit_index));

    opf.pool_index = SYS_USW_ACL_SUDF_AD_INDEX;
    CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, udf_num, udf_index_base));

    /* 2.2 extract Normal SID for fib lookup*/
    if (CTC_FLAG_ISSET(sid_format, SYS_SRV6_SID_FORMAT_NORMAL))
    {
        for (i = 0; i < SYS_SRV6_RSV_UDF_FOR_SID; i++)
        {
            sal_memset(&result, 0, sizeof(result));
            if (i > 0 && i <= 3)       /*index 1-3 is used for extract SIDs */
            {
                for (j = 0; j < 8; j++)/*extract SRH[SL] for fib lookup*/
                {
                    SetParserUdfCamResult(V, udfStartPosType7_f - j, &result, DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L3));
                    SetParserUdfCamResult(V, udfEntryOffset7_f - j, &result, ((SYS_SID_OFFSET + 16*(i - 1 )) >> 1) + j);
                }
            }
            else                       /*index 4-7 is used for extract SRH */
            {
                for (j = 0; j < 4; j++)
                {
                    SetParserUdfCamResult(V, udfStartPosType0_f + j, &result, DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L3));
                    SetParserUdfCamResult(V, udfEntryOffset0_f + j, &result, ((SYS_SRH_OFFSET + (2 * j)) >> 1));
                }
            }
            SetParserUdfCamResult(A, udfMask_f, &result, udfMask);
            SetParserUdfCamResult(V, fibKeyUdfSelType_f, &result, 1);
            SetParserUdfCamResult(V, udfMappedIndex_f, &result, udf_hit_index);
            cmd = DRV_IOW(ParserUdfCamResult1_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, *udf_index_base + i , DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &result));
        }
    }

    if (CTC_FLAG_ISSET(sid_format, SYS_SRV6_SID_FORMAT_USID))
    {
        /* 2.3 extract uSID for fib lookup*/
        sal_memset(&result, 0, sizeof(result));
        for (j = 0; j < 7; j++)
        {
            SetParserUdfCamResult(V, udfStartPosType7_f - j, &result, DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L3));
            SetParserUdfCamResult(V, udfEntryOffset7_f - j, &result, (SYS_DIP_OFFSET / 2) + j + 1);
        }
        SetParserUdfCamResult(V, udfEntryOffset7_f , &result, (SYS_DIP_OFFSET / 2));
        if ((SYS_SRV6_USID_PREFIX_LEN_16 + SYS_SRV6_USID_USID_LEN) == usid_prefix_len)/* 16bits uSID block + 16bits uSID, skip byte2~3 */
        {
            SetParserUdfCamResult(V, udfEntryOffset6_f , &result, (SYS_DIP_OFFSET / 2) + 2);
        }
        else if ((SYS_SRV6_USID_PREFIX_LEN_32 + SYS_SRV6_USID_USID_LEN) == usid_prefix_len)/* 32bits uSID block + 16bits uSID, skip byte4~5 */
        {
            SetParserUdfCamResult(V, udfEntryOffset6_f , &result, (SYS_DIP_OFFSET / 2) + 1);
        }
        else if ((SYS_SRV6_USID_PREFIX_LEN_48 + SYS_SRV6_USID_USID_LEN) == usid_prefix_len)/* 48bits uSID block + 16bits uSID, skip byte6~7 */
        {
            SetParserUdfCamResult(V, udfEntryOffset6_f , &result, (SYS_DIP_OFFSET / 2) + 1);
            SetParserUdfCamResult(V, udfEntryOffset5_f , &result, (SYS_DIP_OFFSET / 2) + 2);
        }
        SetParserUdfCamResult(A, udfMask_f, &result, udfMask);
        SetParserUdfCamResult(V, fibKeyUdfSelType_f, &result, 1);
        SetParserUdfCamResult(V, udfMappedIndex_f, &result, udf_hit_index);
        cmd = DRV_IOW(ParserUdfCamResult1_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, *udf_index_base + sid_num, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &result));
    }
    else if (CTC_FLAG_ISSET(sid_format, SYS_SRV6_SID_FORMAT_GSID))
    {
        uint32 prefix_shift = 0;
        uint32 field_id_type = 0;
        uint32 field_id_offset = 0;

        prefix_shift = (gsid_prefix_len-SYS_SRV6_GSID_GSID_LEN)/16;
        field_id_type = ParserUdfCamResult_udfStartPosType7_f-prefix_shift;
        field_id_offset = ParserUdfCamResult_udfEntryOffset7_f-prefix_shift;
        /* 2.4 extract gSID for fib lookup*/
        for (i = 0; i < SYS_SRV6_RSV_UDF_FOR_GSID; i++)
        {
            sal_memset(&result, 0, sizeof(result));
            for (j = 0; j < prefix_shift; j++)
            {
                SetParserUdfCamResult(V, udfStartPosType7_f - j, &result, DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L3));
                SetParserUdfCamResult(V, udfEntryOffset7_f - j, &result, (SYS_DIP_OFFSET / 2) + j);
            }
            for (j = 0; j < 2; j++)
            {
                DRV_SET_FIELD_V(lchip, ParserUdfCamResult_t, field_id_type-j, &result, DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L3));
                DRV_SET_FIELD_V(lchip, ParserUdfCamResult_t, field_id_offset-j, &result, (SYS_SID_OFFSET / 2) + j + (i * 2));
            }
            SetParserUdfCamResult(A, udfMask_f, &result, udfMask);
            SetParserUdfCamResult(V, fibKeyUdfSelType_f, &result, 1);
            SetParserUdfCamResult(V, udfMappedIndex_f, &result, udf_hit_index);
            cmd = DRV_IOW(ParserUdfCamResult1_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, *udf_index_base + sid_num + i, DRV_CMD_BMP_EN(cmd,
                              MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &result));  /* Base + normal_sid(4) + i(from 0) */
        }
    }

    if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
    {
        /* 3. Flow UDF for acl lookup, only extract srh. ParserUdfCamResult0_t */
        for (i = 0; i < SYS_SRV6_RSV_UDF_FOR_SID; i++)
        {
            sal_memset(&result, 0, sizeof(result));
            SetParserUdfCamResult(V, skipVlanTag_f, &result, 1);
            for (j = 0; j < 4; j++)
            {
                SetParserUdfCamResult(V, udfStartPosType0_f + j, &result, DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L3));
                SetParserUdfCamResult(V, udfEntryOffset0_f + j, &result, ((SYS_SRH_OFFSET + (2 * j)) >> 1));
            }
            SetParserUdfCamResult(A, udfMask_f, &result, udfMask);
            SetParserUdfCamResult(V, udfMappedIndex_f, &result, udf_hit_index);
            cmd = DRV_IOW(ParserUdfCamResult0_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, *udf_index_base + i , DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &result));
        }

        /* 4. Using ParserUdfCamResult1/ParserUdfCamResult0 index
               (MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM) - SYS_ACL_UDE_RSV_PRI(SYS_ACL_UDF_RSV_SRV6)) to extract srh for bfd */
        sal_memset(&result, 0, sizeof(result));
        SetParserUdfCamResult(V, skipVlanTag_f, &result, 1);
        for (i = 0; i < 4; i++)
        {
            SetParserUdfCamResult(V, udfStartPosType0_f + i, &result, DRV_ENUM(DRV_UDFPOSTYPE_OUTER_L3));
            SetParserUdfCamResult(V, udfEntryOffset0_f + i, &result, ((SYS_SRH_OFFSET + (2 * i)) >> 1));
        }
        SetParserUdfCamResult(A, udfMask_f, &result, udfMask);
        SetParserUdfCamResult(V, udfMappedIndex_f, &result, udf_hit_index);
        cmd = DRV_IOW(ParserUdfCamResult0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, (MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM) - SYS_ACL_UDE_RSV_PRI(SYS_ACL_UDF_RSV_SRV6)),
                         DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &result));
        cmd = DRV_IOW(ParserUdfCamResult1_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, (MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM) - SYS_ACL_UDE_RSV_PRI(SYS_ACL_UDF_RSV_SRV6)),
                          DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &result));

        p_usw_acl_master[lchip]->srv6_rsv_udf_idx = udf_hit_index;
    }
    return CTC_E_NONE;
}

int32
sys_usw_acl_add_udf_entry(uint8 lchip,  ctc_acl_classify_udf_t* p_udf_entry)
{
    sys_acl_udf_entry_t    *p_sys_udf_entry = NULL, *p_sys_udf_entry2 = NULL;
    ParserUdfCamResult_m udf_rst[SYS_UDF_CAM_TYPE_NUM];
    ParserUdfCam_m udf_cam;
    uint8 offset_type = 0;
    sys_usw_opf_t   opf;
    uint32 offset = 0;
    uint8  remainder = 0;
    uint8  is_update = 0;
    uint8 add_udf_vec = 0;
    uint8  udf_mask_full[CTC_ACL_UDF_BYTE_NUM];
    uint8  udf_type_none[CTC_ACL_UDF_FIELD_NUM] = {CTC_ACL_UDF_TYPE_NONE};
    int32    ret = 0;
    sys_acl_traverse_data_t  user_data;
    sys_acl_udf_ad_t *p_sys_udf_ad = NULL;

    sal_memset(&opf, 0, sizeof(opf));
    sal_memset(udf_mask_full, 0xFF, sizeof(udf_mask_full));
    sal_memset(&udf_cam, 0, sizeof(ParserUdfCam_m));
    sal_memset(&user_data, 0, sizeof(sys_acl_traverse_data_t));

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_udf_entry);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "acl_add_udf_entry,udf_id: %u,priority:%d \n", p_udf_entry->udf_id, p_udf_entry->priority);

    if (MCHIP_ACL(lchip)->add_udf_entry)
    {
        SYS_USW_ACL_LOCK(lchip);
        SYS_USW_ACL_RETURN_UNLOCK(MCHIP_ACL(lchip)->add_udf_entry(lchip, p_udf_entry));
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NONE;
    }

    if (p_udf_entry->shared_udf && p_udf_entry->sudf_en)
    {
        p_udf_entry->udf_ad_id +=(MCHIP_CAP(SYS_CAP_ACL_SUDF_AD_ID_MIN)-1);
        CTC_VALUE_RANGE_CHECK(p_udf_entry->udf_ad_id, MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM), MCHIP_CAP(SYS_CAP_ACL_UDF_AD_ID_MAX))
    }
    else if(p_udf_entry->shared_udf && !p_udf_entry->sudf_en)
    {
        CTC_VALUE_RANGE_CHECK(p_udf_entry->udf_ad_id, MCHIP_CAP(SYS_CAP_ACL_UDF_AD_ID_MIN), MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM)-1)
    }

    CTC_MAX_VALUE_CHECK(p_udf_entry->priority, 0xF);
    CTC_MAX_VALUE_CHECK(p_udf_entry->offset_type, CTC_ACL_UDF_OFFSET_L4);
    CTC_MAX_VALUE_CHECK(p_udf_entry->offset_type_array[0], CTC_ACL_UDF_OFFSET_L4);
    CTC_MAX_VALUE_CHECK(p_udf_entry->offset_type_array[1], CTC_ACL_UDF_OFFSET_L4);
    CTC_MAX_VALUE_CHECK(p_udf_entry->offset_type_array[2], CTC_ACL_UDF_OFFSET_L4);
    CTC_MAX_VALUE_CHECK(p_udf_entry->offset_type_array[3], CTC_ACL_UDF_OFFSET_L4);

    remainder = (p_udf_entry->offset[0] % 4) || (p_udf_entry->offset[1] % 4) || (p_udf_entry->offset[2] % 4) || (p_udf_entry->offset[3] % 4);
    if(remainder)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "The offset :offset[0]:%d,offset[1]:%d,offset[2]:%d,offset[3]:%d\n", p_udf_entry->offset[0],p_udf_entry->offset[1],p_udf_entry->offset[2],p_udf_entry->offset[3]);
        return CTC_E_INVALID_PARAM;
    }

    CTC_MAX_VALUE_CHECK(p_udf_entry->offset[0]/4, MCHIP_CAP(SYS_CAP_ACL_UDF_OFFSET_MAX));
    CTC_MAX_VALUE_CHECK(p_udf_entry->offset[1]/4, MCHIP_CAP(SYS_CAP_ACL_UDF_OFFSET_MAX));
    CTC_MAX_VALUE_CHECK(p_udf_entry->offset[2]/4, MCHIP_CAP(SYS_CAP_ACL_UDF_OFFSET_MAX));
    CTC_MAX_VALUE_CHECK(p_udf_entry->offset[3]/4, MCHIP_CAP(SYS_CAP_ACL_UDF_OFFSET_MAX));
    CTC_MAX_VALUE_CHECK(p_udf_entry->offset_num, 4);
    SYS_USW_ACL_LOCK(lchip);

    _sys_usw_acl_get_udf_info(lchip,  p_udf_entry->udf_id, &p_sys_udf_entry2);

    if(p_sys_udf_entry2 )
    {
        is_update = 1;
    }

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_get_udf_entry_by_priority(lchip, p_udf_entry->priority, &p_sys_udf_entry));
    if((!p_sys_udf_entry || p_sys_udf_entry->udf_id != p_udf_entry->udf_id) && is_update)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PARAM);
    }
    if(p_sys_udf_entry && p_sys_udf_entry->key_index_used && !is_update)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_EXIST);
    }
    if(!is_update)
    {

        MALLOC_ZERO(MEM_ACL_MODULE, p_sys_udf_entry, sizeof(sys_acl_udf_entry_t));
        if (NULL == p_sys_udf_entry)
        {
            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NO_MEMORY);
        }
        if (!p_udf_entry->shared_udf)
        {
            opf.pool_type  = p_usw_acl_master[lchip]->opf_type_udf;
            opf.pool_index = SYS_USW_ACL_UDF_MAPPED_INDEX;
            opf.multiple = 0;
            ret =  sys_usw_opf_alloc_offset(lchip, &opf, 1, &offset);
            if(ret < 0)
            {
                CTC_ERROR_GOTO(CTC_E_NO_RESOURCE, ret, free_mem);
            }

            p_sys_udf_entry->udf_hit_index = offset & 0xF;
            p_udf_entry->udf_ad_id = p_sys_udf_entry->udf_hit_index;
        }
        else
        {
            p_sys_udf_entry->udf_hit_index = p_udf_entry->udf_ad_id;
        }
        p_sys_udf_ad = ctc_vector_get(p_usw_acl_master[lchip]->udf_ad, p_sys_udf_entry->udf_hit_index);
        if(!p_sys_udf_ad)
        {
            add_udf_vec = 1;
            MALLOC_ZERO(MEM_ACL_MODULE, p_sys_udf_ad, sizeof(sys_acl_udf_ad_t));
            if (NULL == p_sys_udf_ad)
            {
                CTC_ERROR_GOTO(CTC_E_NO_RESOURCE,ret,error1)
            }
            if (!ctc_vector_add(p_usw_acl_master[lchip]->udf_ad, p_sys_udf_entry->udf_hit_index, p_sys_udf_ad))
            {
                ret = CTC_E_NO_MEMORY;
                goto error2;
            }
            if(p_udf_entry->shared_udf)
            {
                opf.pool_type  = p_usw_acl_master[lchip]->opf_type_udf;
                opf.pool_index = SYS_USW_ACL_UDF_MAPPED_INDEX;
                opf.multiple = 0;
                CTC_ERROR_GOTO(sys_usw_opf_alloc_offset_from_position(lchip, &opf, 1,p_udf_entry->udf_ad_id),ret,error3)
            }
        }
        p_sys_udf_ad->ref_cnt++;
        p_sys_udf_entry->key_index = SYS_ACL_UDF_PRI_2_IDX(p_udf_entry->priority);
    }
    else
    {
        if(p_udf_entry->shared_udf && p_sys_udf_entry->udf_hit_index != p_udf_entry->udf_ad_id)/*not support update udf_ad_id*/
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "not support update udf_ad_id");
            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PARAM);
        }
        p_udf_entry->udf_ad_id = p_sys_udf_entry2->udf_hit_index;/*update,return have allocated udf_ad_id*/
    }

    p_sys_udf_entry->udf_offset_num = p_udf_entry->offset_num;
    sal_memset(&udf_rst, 0, sizeof(ParserUdfCamResult_m));
    SetParserUdfCamResult(V, skipTcpOption_f, &udf_rst, p_udf_entry->tcp_option_en?1:0);
    SetParserUdfCamResult(V, udfEntryOffset0_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], p_udf_entry->offset[0]/4);
    SetParserUdfCamResult(V, udfEntryOffset1_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], p_udf_entry->offset[1]/4);
    SetParserUdfCamResult(V, udfEntryOffset2_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], p_udf_entry->offset[2]/4);
    SetParserUdfCamResult(V, udfEntryOffset3_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], p_udf_entry->offset[3]/4);
    SetParserUdfCamResult(V, udfMappedIndex_f, &udf_rst, p_sys_udf_entry->udf_hit_index);

    if (CTC_ACL_UDF_TYPE_NONE != p_udf_entry->offset_type)      /*Compatible with D2*/
    {
        offset_type = sys_usw_acl_map_ctc_to_sys_offset_type(lchip, p_udf_entry->offset_type);
        SetParserUdfCamResult(V, udfStartPosType_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], offset_type);
        SetParserUdfCamResult(V, udfStartPosType0_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], offset_type);
        SetParserUdfCamResult(V, udfStartPosType1_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], offset_type);
        SetParserUdfCamResult(V, udfStartPosType2_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], offset_type);
        SetParserUdfCamResult(V, udfStartPosType3_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], offset_type);
    }
    else if (sal_memcmp(p_udf_entry->offset_type_array, udf_type_none, sizeof(p_udf_entry->offset_type_array)))
    {
        if (DRV_FLD_IS_EXISIT(ParserUdfCamResult_t, ParserUdfCamResult_udfStartPosType_f))
        {
            CTC_ERROR_GOTO(CTC_E_NOT_SUPPORT, ret, error4);
        }
        offset_type = sys_usw_acl_map_ctc_to_sys_offset_type(lchip, p_udf_entry->offset_type_array[0]);
        SetParserUdfCamResult(V, udfStartPosType0_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], offset_type);
        offset_type = sys_usw_acl_map_ctc_to_sys_offset_type(lchip, p_udf_entry->offset_type_array[1]);
        SetParserUdfCamResult(V, udfStartPosType1_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], offset_type);
        offset_type = sys_usw_acl_map_ctc_to_sys_offset_type(lchip, p_udf_entry->offset_type_array[2]);
        SetParserUdfCamResult(V, udfStartPosType2_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], offset_type);
        offset_type = sys_usw_acl_map_ctc_to_sys_offset_type(lchip, p_udf_entry->offset_type_array[3]);
        SetParserUdfCamResult(V, udfStartPosType3_f, &udf_rst[SYS_UDF_CAM_TYPE_FIB], offset_type);
    }
    else
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "UDF offset type is invalid!\n");
        CTC_ERROR_GOTO(CTC_E_INVALID_PARAM, ret, error4);
    }

    CTC_ERROR_GOTO(sys_usw_parser_io_set_parser_udf_cam_result(lchip, &udf_rst[SYS_UDF_CAM_TYPE_FIB],p_sys_udf_entry->key_index,p_udf_entry->sudf_en, p_usw_acl_master[lchip]->udf_mode), ret, error4);

    if(!is_update)
    {
        sal_memset(&udf_cam, 0, sizeof(ParserUdfCam_m));
        SetParserUdfCam(V, entryValid_f, &udf_cam, 0);
        CTC_ERROR_GOTO(sys_usw_parser_io_set_parser_udf_cam(lchip, &udf_cam,p_sys_udf_entry->key_index), ret, error4);
    }
    p_sys_udf_entry->udf_id = p_udf_entry->udf_id;
    p_sys_udf_entry->key_index_used = 1;
    if (!is_update)
    {
        ctc_hash_insert(p_usw_acl_master[lchip]->udf_entry, p_sys_udf_entry);
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_UDF_ENTRY, 1);
    }

    SYS_USW_ACL_UNLOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MASTER, 1);
    return CTC_E_NONE;

error4:
    if(!is_update)
    {
        p_sys_udf_ad->ref_cnt--;
        if(add_udf_vec && p_udf_entry->shared_udf)
        {
            opf.pool_index =  SYS_USW_ACL_UDF_MAPPED_INDEX;
            sys_usw_opf_free_offset(lchip, &opf, 1, p_udf_entry->udf_ad_id);
        }
    }
error3:
    if(!is_update && add_udf_vec)
    {
        ctc_vector_del(p_usw_acl_master[lchip]->udf_ad, p_sys_udf_entry->udf_hit_index);
    }
error2:
    if(!is_update && add_udf_vec)
    {
        mem_free(p_sys_udf_ad);
    }
error1:
    if(!is_update && !p_udf_entry->shared_udf)
    {
        opf.pool_index = SYS_USW_ACL_UDF_MAPPED_INDEX;
        sys_usw_opf_free_offset(lchip, &opf, 1, p_sys_udf_entry->udf_hit_index);
    }
free_mem:
    if (!is_update)
    {
        mem_free(p_sys_udf_entry);
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

#if 0
int32
sys_usw_acl_get_udf_key_index(uint8 lchip,  uint32 udf_id, uint32* index)
{
    sys_acl_udf_entry_t    *p_sys_udf_entry = NULL;
    SYS_ACL_INIT_CHECK();
    SYS_USW_ACL_LOCK(lchip);
    _sys_usw_acl_get_udf_info(lchip,  udf_id, &p_sys_udf_entry);
    if (NULL == p_sys_udf_entry)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_EXIST);
    }
    *index = p_sys_udf_entry->key_index;
    SYS_USW_ACL_UNLOCK(lchip);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MASTER, 1);
    return CTC_E_NONE;
}
#endif

int32
sys_usw_acl_remove_udf_entry(uint8 lchip,  ctc_acl_classify_udf_t* p_udf_entry)
{
    uint32 cmd = 0;
    sys_acl_udf_entry_t    *p_sys_udf_entry;
    sys_usw_opf_t   opf;
    ParserUdfCam_m udf_cam;
    tbl_entry_t   tcam_key;
    sys_acl_udf_ad_t *p_sys_udf_ad = NULL;

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_udf_entry);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "remove_udf_entry,udf_id: %u\n", p_udf_entry->udf_id);

    SYS_USW_ACL_LOCK(lchip);
    _sys_usw_acl_get_udf_info(lchip,  p_udf_entry->udf_id, &p_sys_udf_entry);

    if (!p_sys_udf_entry || !p_sys_udf_entry->key_index_used)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_EXIST);
    }
    p_sys_udf_ad = ctc_vector_get(p_usw_acl_master[lchip]->udf_ad, p_sys_udf_entry->udf_hit_index);
    if(!p_sys_udf_ad)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_EXIST);
    }
    else
    {
        p_sys_udf_ad->ref_cnt--;
    }
    /* remove from hash */
    ctc_hash_remove(p_usw_acl_master[lchip]->udf_entry, p_sys_udf_entry);

    opf.pool_type  = p_usw_acl_master[lchip]->opf_type_udf;
    opf.multiple = 0;

    if (p_sys_udf_ad->ref_cnt == 0)
    {
        opf.pool_index = p_sys_udf_entry->is_sudf? SYS_USW_ACL_UDF_MAPPED_INDEX1: SYS_USW_ACL_UDF_MAPPED_INDEX;
        sys_usw_opf_free_offset(lchip, &opf, 1, p_sys_udf_entry->udf_hit_index);
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "%s free udf mapped index: %u\n", p_sys_udf_entry->is_sudf ? "sudf" : "", p_sys_udf_entry->udf_hit_index);
        p_sys_udf_ad = ctc_vector_del(p_usw_acl_master[lchip]->udf_ad, p_sys_udf_entry->udf_hit_index);
        mem_free(p_sys_udf_ad);
    }
    if(p_sys_udf_entry->is_sudf)
    {
        opf.pool_index = SYS_USW_ACL_SUDF_AD_INDEX;
        sys_usw_opf_free_offset(lchip, &opf, 1, p_sys_udf_entry->key_index); /* p_sys_udf_entry->key_index is used as ad_index */
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "free sudf ad index: %u\n", p_sys_udf_entry->key_index);
    }
    if(p_usw_acl_master[lchip]->udf_fpa_en)
    {
        fpa_usw_free_offset(&p_usw_acl_master[lchip]->udf_block.fpab, p_sys_udf_entry->fpae.offset_a);
    }

    /*save to DB*/
    p_sys_udf_entry->key_index_used = 0;
    p_sys_udf_entry->ip_op = 0;
    p_sys_udf_entry->ip_frag = 0;
    p_sys_udf_entry->mpls_num = 0;
    p_sys_udf_entry->l4_type = 0;
    p_sys_udf_entry->udf_offset_num = 0;
    p_sys_udf_entry->ip_protocol = 0;

    /*remove buffer*/
    if(p_sys_udf_entry->buffer)
    {
        mem_free(p_sys_udf_entry->buffer);
    }

    if(DRV_FROM_TMM(lchip) )
    {
        ParserUdfCamResult_m udf_rst[SYS_UDF_CAM_TYPE_NUM];
        sal_memset(udf_rst, 0, SYS_UDF_CAM_TYPE_NUM * sizeof(ParserUdfCamResult_m));
        if((!p_sys_udf_entry->is_sudf))
        {
            cmd = DRV_IOD(ParserUdfCam_t, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, p_sys_udf_entry->key_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &tcam_key);
        }
        sys_usw_parser_io_set_parser_udf_cam_result(lchip, udf_rst, p_sys_udf_entry->key_index, p_sys_udf_entry->is_sudf, p_usw_acl_master[lchip]->udf_mode);
    }
    else
    {
        sys_usw_parser_io_get_parser_udf_cam(lchip, &udf_cam, p_sys_udf_entry->key_index);
        SetParserUdfCam(V, entryValid_f, &udf_cam, 0);
        sys_usw_parser_io_set_parser_udf_cam(lchip, &udf_cam, p_sys_udf_entry->key_index);
    }
    if(DRV_FROM_AT(lchip) && p_usw_acl_master[lchip]->udf_mode && !p_sys_udf_entry->is_sudf )/*tmm udf mode in arctic,!service udf ,relese old opf*/
    {
        opf.pool_type  = p_usw_acl_master[lchip]->opf_type_udf;
        opf.multiple = 0;
        opf.pool_index = SYS_USW_ACL_SUDF_AD_INDEX;
        sys_usw_opf_free_offset(lchip,&opf, 1, MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM)+p_sys_udf_entry->key_index);
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "free udf ad index: %u\n", MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM)+p_sys_udf_entry->key_index);
    }
    if(MCHIP_ACL(lchip)->enable_udf_ipfix)
    {
       MCHIP_ACL(lchip)->enable_udf_ipfix(lchip,p_sys_udf_entry->udf_hit_index,0);
    }
        /* memory free udf entry*/
    if(p_sys_udf_entry)
    {
        mem_free(p_sys_udf_entry);
    }
    if(DRV_FROM_AT(lchip))
    {/* if parser udf not exist, udf can change match xdata */
        opf.pool_type  = p_usw_acl_master[lchip]->opf_type_udf;
        opf.multiple = 0;
        opf.pool_index = SYS_USW_ACL_UDF_MAPPED_INDEX;
        if(!sys_usw_opf_get_alloced_cnt(lchip, &opf))
        {
           p_usw_acl_master[lchip]->udf_xdata_used = 0;
        }
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_UDF_ENTRY, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MASTER, 1);
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_acl_add_udf_entry_key_field(uint8 lchip,  uint32 udf_id, ctc_field_key_t* key_field)
{
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"add_udf_entry_key_filed,udf_id: %u,key_field_type:%d \n", udf_id,key_field->type);

    SYS_ACL_INIT_CHECK();
    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_check_udf_entry_key_field_union(lchip,  udf_id,  key_field));
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_add_udf_entry_key_field(lchip,  udf_id,  key_field,1));
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_set_udf_entry_key_field_union(lchip,  udf_id, key_field,1));
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_acl_remove_udf_entry_key_field(uint8 lchip, uint32 udf_id, ctc_field_key_t* key_field)
{
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"remove_udf_entry_key_filed,udf_id: %u,key_field_type:%d \n", udf_id,key_field->type);

    SYS_ACL_INIT_CHECK();
    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_check_udf_entry_key_field_union(lchip,  udf_id,  key_field));
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_add_udf_entry_key_field(lchip,  udf_id,  key_field,0));
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_set_udf_entry_key_field_union( lchip,  udf_id, key_field,0));
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_acl_dump_udf_entry_info_cb(void* bucket_data, void* user_data)
{
    uint8 lchip = 0;
    uint8 loop_j = 0;
    uint16 entry_num = 0;
    uint16 priority = 0;
    char str_tmp[15] = "-";
    char flag[10] = {0};
    char mask_tmp1[20] = {0};
    char type_str[64] = {0};
    char offset_str[64] = "(";
    sys_acl_udf_entry_t    *p_sys_udf_entry = NULL;
    ctc_acl_classify_udf_t  udf_entry, scl_key;

    sal_memset(&udf_entry, 0, sizeof(ctc_acl_classify_udf_t));
    sal_memset(&scl_key, 0, sizeof(ctc_acl_classify_udf_t));

    p_sys_udf_entry = (sys_acl_udf_entry_t*)bucket_data;
    lchip   = ((sys_acl_traverse_data_t*)user_data)->value0;
    entry_num = *((uint16*)((sys_acl_traverse_data_t*)user_data)->data0);

    udf_entry.scl_key = &scl_key;
    CTC_ERROR_RETURN(sys_usw_acl_udf_map_sys_to_ctc(lchip, p_sys_udf_entry, &udf_entry));

    sal_memset(flag, 0, sizeof(flag));
    sal_memset(mask_tmp1, 0, sizeof(mask_tmp1));
    sal_memset(type_str, 0, sizeof(type_str));
    sal_memset(offset_str, 0, sizeof(offset_str));
    sal_strcpy(offset_str, "(");
    if (p_sys_udf_entry->is_sudf)
    {
        sal_strcat(flag, "F");
    }
    if (p_sys_udf_entry->key_index_used)
    {
        sal_strcat(flag, "P");
    }
    if (udf_entry.valid)
    {
        sal_strcat(flag, "A");
    }
    if (udf_entry.skip_vlan)
    {
        sal_strcat(flag, "V");
    }
    if (udf_entry.tcp_option_en)
    {
        sal_strcat(flag, "T");
    }


    priority = SYS_ACL_UDF_IDX_2_PRI(lchip, p_sys_udf_entry);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "udf entry priority: %u key index: %u\n", priority, p_sys_udf_entry->key_index);

    if(0 == p_sys_udf_entry->is_sudf)
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-3d %-4d( %5d / %-5d) %-10u %-5s %-2d",
            entry_num,priority,p_sys_udf_entry->key_index,p_sys_udf_entry->key_index,p_sys_udf_entry->udf_id,flag,p_sys_udf_entry->granularity);
    }
    else
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-3d %-4s( %5s / %-5d) %-10u %-5s %-2d",
            entry_num,str_tmp,"-",(DRV_FROM_AT(lchip)? p_sys_udf_entry->key_index & 0x1FF:p_sys_udf_entry->key_index),p_sys_udf_entry->udf_id,flag,p_sys_udf_entry->granularity);
    }

    /* offset_type */
    if (udf_entry.offset_type)
    {
         SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-1d(", udf_entry.offset_type);
    }
    else
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " -(");
    }

    for (loop_j=0; loop_j<8; loop_j++)
    {
        if (udf_entry.offset_type_array[loop_j])
        {
            sal_sprintf(mask_tmp1, "%d",  udf_entry.offset_type_array[loop_j]);
        }
        else
        {
            sal_sprintf(mask_tmp1, "%s",  "-");
        }
        sal_strcat(mask_tmp1, (7 == loop_j)?")":"|");
        sal_strcat(type_str, mask_tmp1);

        if (loop_j < udf_entry.offset_num)
        {
            sal_sprintf(mask_tmp1, "%d",  udf_entry.offset[loop_j]);
        }
        else
        {
            sal_sprintf(mask_tmp1, "%s",  "-");
        }
        sal_strcat(mask_tmp1, (7 == loop_j)?")":"|");
        sal_strcat(offset_str, mask_tmp1);
    }

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"%-16s", type_str);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP," %-33s\n", offset_str);

    entry_num++;
    *((uint16*)((sys_acl_traverse_data_t*)user_data)->data0) = entry_num;

    return CTC_E_NONE;
}

int32
sys_usw_acl_dump_udf_entry_info(uint8 lchip)
{
    uint16 entry_num = 0;
    sys_acl_traverse_data_t  user_data;

    sal_memset(&user_data, 0, sizeof(sys_acl_traverse_data_t));

    SYS_ACL_INIT_CHECK();

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"=================== UDF Overall Status ===================\n");
    if(DRV_FROM_TMM(lchip))
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"UDF Key Table Name :%s\n","ParserUdfCam(512)");
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"UDF Action Table Name :%s\n",DRV_FROM_AT(lchip)? "ParserUdfCamResult(512)":"ParserUdfCamResult(1024)");
    }
    else
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"UDF Key Table Name :%s\n","ParserUdfCam(16)");
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"UDF Action Table Name :%s\n","ParserUdfCamResult(16)");
    }
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"OffsetType :0-Invalid; 1-L2 Header; 2:L3 Header; 3-L4 Header; 4-Raw packet header\n");
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Flags: F-SUDF;  P-Priority Used;  A-Valid;  V-Skip Vlan;  T-Skip TcpOp\n");

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"No. Pri (key-Idx/ad-Idx) UDF-ID     Flags Gr Offset-Type(0-7)   Offset-Array(0-7)\n");
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"-----------------------------------------------------------------------------------\n");

    SYS_USW_ACL_LOCK(lchip);

    user_data.data0 = (void*)&(entry_num);
    user_data.value0 = lchip;
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(ctc_hash_traverse(p_usw_acl_master[lchip]->udf_entry, sys_usw_acl_dump_udf_entry_info_cb, (void*) (&user_data)));

    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

#define _ACL_L4PORT_RANGE_
int32
sys_usw_acl_build_field_range(uint8 lchip, uint8 dir, uint8 range_type, uint16 min, uint16 max, uint16* p_range_bitmap, uint8 is_add)
{
    int32 ret = CTC_E_NONE;
    SYS_USW_ACL_LOCK(lchip);
    if(is_add)
    {
        ret = (_sys_usw_acl_add_field_range(lchip, dir, range_type, min, max, p_range_bitmap));
    }
    else
    {
        ret = (_sys_usw_acl_remove_field_range(lchip, dir, range_type, 0, p_range_bitmap));
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}


#define _ACL_CRYPT_ERROR_TO_CPU_
int32
sys_usw_acl_set_wlan_crypt_error_to_cpu_en(uint8 lchip, uint8 enable)
{
    int32 ret = 0;
    uint32 cmd = 0;
    uint8 step = 1;
    uint16 idx = 0;
    IpeFwdCtl_m ipe_fwd;
    IpeAclQosCtl_m ipe_acl_qos_ctl;
    uint16 lport = 0;
    uint8 gchip = 0;
    uint32 gport = 0;
    sys_acl_group_t* pg = NULL;
    sys_acl_entry_t* pe_lkup = NULL;
    ctc_acl_entry_t* p_acl_entry = NULL;
    ctc_acl_property_t acl_prop;
    ctc_acl_group_info_t acl_group;
    ctc_field_key_t key_field;
    ctc_acl_field_action_t action_field;
    ctc_acl_to_cpu_t acl_to_cpu;
    sys_acl_block_t* pb = NULL;
    sys_acl_league_t* p_sys_league = NULL;

    SYS_ACL_INIT_CHECK();

    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(sys_usw_get_gchip_id(lchip, &gchip));

    sal_memset(&ipe_fwd, 0, sizeof(IpeFwdCtl_m));
    sal_memset(&acl_prop, 0, sizeof(ctc_acl_property_t));
    sal_memset(&acl_group, 0, sizeof(ctc_acl_group_info_t));
    sal_memset(&key_field, 0, sizeof(ctc_field_key_t));
    sal_memset(&action_field, 0, sizeof(ctc_acl_field_action_t));
    sal_memset(&acl_to_cpu, 0, sizeof(ctc_acl_to_cpu_t));

    cmd = DRV_IOR(IpeFwdCtl_t, DRV_ENTRY_FLAG);
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_fwd));

    cmd = DRV_IOR(IpeAclQosCtl_t, DRV_ENTRY_FLAG);
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_acl_qos_ctl));

    if (enable && (!p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu))
    {
        /*check resource*/
        pb = &SYS_ACL_BLOCK(lchip, p_usw_acl_master[lchip]->igs_block_num -1);
        p_sys_league = &(p_usw_acl_master[lchip]->league[p_usw_acl_master[lchip]->igs_block_num -1]);
        if (p_sys_league->lkup_level_bitmap == 0)
        {
            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NO_RESOURCE);
        }
        if (pb->fpab.entry_count != pb->fpab.free_count)
        {
            step  = 1;
            for (idx = 0; idx < pb->fpab.entry_count; idx = idx + step)
            {
                if((idx >= pb->fpab.start_offset[CTC_FPA_KEY_SIZE_640]) && (pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_640]))      /*640 bit key*/
                {
                    step = 8;
                }
                else if(idx >= pb->fpab.start_offset[CTC_FPA_KEY_SIZE_320] && (pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_320]))   /*320 bit key*/
                {
                    step = 4;
                }
                else if(idx >= pb->fpab.start_offset[CTC_FPA_KEY_SIZE_160] && (pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_160]))   /*160 bit key*/
                {
                    step = 2;
                }
                else                                            /*80 bit key*/
                {
                    step = 1;
                }

                step = pb->fpab.same_size?1:step;

                if (pb->fpab.entries[idx])
                {
                    if (pb->fpab.entries[idx]->entry_id <= CTC_ACL_MAX_USER_ENTRY_ID)
                    {
                        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NO_RESOURCE);
                    }
                }
            }
        }

        /*create acl group*/
        acl_group.type = CTC_ACL_GROUP_TYPE_PORT_CLASS;
        acl_group.dir = CTC_INGRESS;
        acl_group.priority = p_usw_acl_master[lchip]->igs_block_num -1;
        acl_group.lchip = lchip;
        acl_group.un.port_class_id = 1;
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_create_group(lchip, SYS_ACL_GROUP_ID_WLAN_CRYPT_ERROR, &acl_group));

        /*add acl entry*/
        if(NULL == (p_acl_entry = mem_malloc(MEM_ACL_MODULE, sizeof(ctc_acl_entry_t))))
        {
            SYS_USW_ACL_UNLOCK(lchip);
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_acl_entry, 0, sizeof(ctc_acl_entry_t));
        p_acl_entry->entry_id = 0xFFFFFFFF;
        p_acl_entry->key_type = CTC_ACL_KEY_CID;
        p_acl_entry->mode = 1;
        ret = _sys_usw_acl_add_entry(lchip, SYS_ACL_GROUP_ID_WLAN_CRYPT_ERROR, p_acl_entry);
        mem_free(p_acl_entry);
        if(ret)
        {
            SYS_USW_ACL_UNLOCK(lchip);
            return CTC_E_NO_MEMORY;
        }

        /*add key and action field*/
        action_field.type = CTC_ACL_FIELD_ACTION_CP_TO_CPU;
        action_field.ext_data = &acl_to_cpu;
        acl_to_cpu.mode = CTC_ACL_TO_CPU_MODE_TO_CPU_NOT_COVER;
        acl_to_cpu.cpu_reason_id = CTC_PKT_CPU_REASON_DROP;

        _sys_usw_acl_get_entry_by_eid(lchip, 0xFFFFFFFF, &pe_lkup);
        if (!pe_lkup)
        {
            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_EXIST);
        }
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_add_dsacl_field_wlan_error_to_cpu(lchip, &action_field, pe_lkup, 0, 1));

        /*install acl group*/
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_install_group(lchip, SYS_ACL_GROUP_ID_WLAN_CRYPT_ERROR, NULL));

        for (lport=0; lport<SYS_USW_MAX_PORT_NUM_PER_CHIP; lport++)
        {
            if (lport >= SYS_INTERNAL_PORT_START)
            {
                gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);

                /*enable acl on ipe level 7*/
                acl_prop.acl_en = 1;
                acl_prop.tcam_lkup_type = CTC_ACL_TCAM_LKUP_TYPE_CID;
                acl_prop.direction = CTC_INGRESS;
                acl_prop.acl_priority = p_usw_acl_master[lchip]->igs_block_num -1;
                acl_prop.class_id = 1;

                SYS_USW_ACL_ERROR_RETURN_UNLOCK(sys_usw_port_api_set_acl_property(lchip, gport, &acl_prop));
            }
        }

        p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu = 1;
    }
    else if ((!enable) && p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu)
    {
        for (lport=0; lport<SYS_USW_MAX_PORT_NUM_PER_CHIP; lport++)
        {
            if (lport >= SYS_INTERNAL_PORT_START)
            {
                gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);

                /*enable acl on ipe level 7*/
                acl_prop.acl_en = 0;
                acl_prop.direction = CTC_INGRESS;
                acl_prop.acl_priority = p_usw_acl_master[lchip]->igs_block_num -1;

                SYS_USW_ACL_ERROR_RETURN_UNLOCK(sys_usw_port_api_set_acl_property(lchip, gport, &acl_prop));
            }
        }

        /* check if group exist */
        _sys_usw_acl_get_group_by_gid(lchip, SYS_ACL_GROUP_ID_WLAN_CRYPT_ERROR, &pg);
        if (pg)
        {
    		/*uninstall acl group*/
            SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_uninstall_group(lchip, SYS_ACL_GROUP_ID_WLAN_CRYPT_ERROR));

            /*remove all entry*/
            SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_remove_all_entry(lchip, SYS_ACL_GROUP_ID_WLAN_CRYPT_ERROR));

            /*destroy acl group*/
            SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_destroy_group(lchip, SYS_ACL_GROUP_ID_WLAN_CRYPT_ERROR));
        }

        p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu = 0;
    }

    if (p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu || p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu)
    {
        SetIpeFwdCtl(V, hardErrorDebugEn_f, &ipe_fwd, 1);
        cmd = DRV_IOW(IpeFwdCtl_t, DRV_ENTRY_FLAG);
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_fwd));

        SetIpeAclQosCtl(V, hardErrorDebugEn_f, &ipe_acl_qos_ctl, 1);
        cmd = DRV_IOW(IpeAclQosCtl_t, DRV_ENTRY_FLAG);
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_acl_qos_ctl));
    }
    else if ((!p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu) && (!p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu))
    {
        SetIpeFwdCtl(V, hardErrorDebugEn_f, &ipe_fwd, 0);
        cmd = DRV_IOW(IpeFwdCtl_t, DRV_ENTRY_FLAG);
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_fwd));

        SetIpeAclQosCtl(V, hardErrorDebugEn_f, &ipe_acl_qos_ctl, 0);
        cmd = DRV_IOW(IpeAclQosCtl_t, DRV_ENTRY_FLAG);
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_acl_qos_ctl));
    }

    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_usw_acl_set_dot1ae_crypt_error_to_cpu_en(uint8 lchip, uint8 enable)
{
    int32 ret = 0;
    uint8 i = 0;
    uint32 cmd = 0;
    uint8 step = 1;
    uint16 idx = 0;
    IpeFwdCtl_m ipe_fwd;
    IpeAclQosCtl_m ipe_acl_qos_ctl;
    uint16 lport = 0;
    uint8 gchip = 0;
    uint32 gport = 0;
    sys_acl_group_t* pg = NULL;
    sys_acl_entry_t* pe_lkup = NULL;
    ctc_acl_property_t acl_prop;
    ctc_acl_group_info_t acl_group;
    ctc_acl_entry_t*   p_acl_entry = NULL;
    ctc_field_key_t key_field;
    ctc_acl_field_action_t action_field;
    ctc_acl_to_cpu_t acl_to_cpu;
    sys_acl_block_t* pb = NULL;
    sys_acl_league_t* p_sys_league = NULL;
    uint8 l3type_list[] = {
            CTC_PARSER_L3_TYPE_IP,
            CTC_PARSER_L3_TYPE_IPV4,
            CTC_PARSER_L3_TYPE_IPV6,
            CTC_PARSER_L3_TYPE_MPLS,
            CTC_PARSER_L3_TYPE_MPLS_MCAST,
            CTC_PARSER_L3_TYPE_ARP,
            CTC_PARSER_L3_TYPE_FCOE,
            CTC_PARSER_L3_TYPE_TRILL,
            CTC_PARSER_L3_TYPE_ETHER_OAM,
            CTC_PARSER_L3_TYPE_SLOW_PROTO,
            CTC_PARSER_L3_TYPE_CMAC,
            CTC_PARSER_L3_TYPE_PTP,
            CTC_PARSER_L3_TYPE_SATPDU
        };

    if (DRV_FROM_TMM(lchip))
    {
        return CTC_E_NONE;
    }

    SYS_ACL_INIT_CHECK();

    SYS_USW_ACL_LOCK(lchip);

    SYS_USW_ACL_ERROR_RETURN_UNLOCK(sys_usw_get_gchip_id(lchip, &gchip));

    sal_memset(&ipe_fwd, 0, sizeof(IpeFwdCtl_m));
    sal_memset(&acl_prop, 0, sizeof(ctc_acl_property_t));
    sal_memset(&acl_group, 0, sizeof(ctc_acl_group_info_t));
    sal_memset(&key_field, 0, sizeof(ctc_field_key_t));
    sal_memset(&action_field, 0, sizeof(ctc_acl_field_action_t));
    sal_memset(&acl_to_cpu, 0, sizeof(ctc_acl_to_cpu_t));

    cmd = DRV_IOR(IpeFwdCtl_t, DRV_ENTRY_FLAG);
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_fwd));

    cmd = DRV_IOR(IpeAclQosCtl_t, DRV_ENTRY_FLAG);
    SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_acl_qos_ctl));

    if (enable && (!p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu))
    {
        /*check resource*/
        pb = &SYS_ACL_BLOCK(lchip, p_usw_acl_master[lchip]->igs_block_num -1);
        p_sys_league = &(p_usw_acl_master[lchip]->league[p_usw_acl_master[lchip]->igs_block_num -1]);
        if (p_sys_league->lkup_level_bitmap == 0)
        {
            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NO_RESOURCE);
        }
        if (pb->fpab.entry_count != pb->fpab.free_count)
        {
            step  = 1;
            for (idx = 0; idx < pb->fpab.entry_count; idx = idx + step)
            {
                if((idx >= pb->fpab.start_offset[CTC_FPA_KEY_SIZE_640]) && (pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_640]))      /*640 bit key*/
                {
                    step = 8;
                }
                else if(idx >= pb->fpab.start_offset[CTC_FPA_KEY_SIZE_320] && (pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_320]))   /*320 bit key*/
                {
                    step = 4;
                }
                else if(idx >= pb->fpab.start_offset[CTC_FPA_KEY_SIZE_160] && (pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_160]))   /*160 bit key*/
                {
                    step = 2;
                }
                else                                            /*80 bit key*/
                {
                    step = 1;
                }

                step = pb->fpab.same_size?1:step;

                if (pb->fpab.entries[idx])
                {
                    if (pb->fpab.entries[idx]->entry_id <= CTC_ACL_MAX_USER_ENTRY_ID)
                    {
                        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NO_RESOURCE);
                    }
                }
            }
        }

        /*create acl group*/
        acl_group.type = CTC_ACL_GROUP_TYPE_PORT_CLASS;
        acl_group.dir = CTC_INGRESS;
        acl_group.priority = p_usw_acl_master[lchip]->igs_block_num -1;
        acl_group.lchip = lchip;
        acl_group.un.port_class_id = 2;
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_create_group(lchip, SYS_ACL_GROUP_ID_DOT1AE_CRYPT_ERROR, &acl_group));

        /*add acl entry*/
        if(NULL == (p_acl_entry = mem_malloc(MEM_ACL_MODULE, sizeof(ctc_acl_entry_t))))
        {
            SYS_USW_ACL_UNLOCK(lchip);
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_acl_entry, 0, sizeof(ctc_acl_entry_t));
        for (i=0; i<sizeof(l3type_list); i++)
        {
            p_acl_entry->key_type = CTC_ACL_KEY_CID;
            p_acl_entry->mode = 1;
            p_acl_entry->entry_id = 0xFFFFFFFE - i;
            ret = ret ? ret : (_sys_usw_acl_add_entry(lchip, SYS_ACL_GROUP_ID_DOT1AE_CRYPT_ERROR, p_acl_entry));
        }
        mem_free(p_acl_entry);
        if(ret)
        {
            SYS_USW_ACL_UNLOCK(lchip);
            return ret;
        }
        /*add key and action field*/
        for (i=0; i<sizeof(l3type_list); i++)
        {
            key_field.type = CTC_FIELD_KEY_L3_TYPE;
            key_field.mask = 0xff;
            key_field.data = l3type_list[i];
            _sys_usw_acl_get_entry_by_eid(lchip, 0xFFFFFFFE - i, &pe_lkup);
            if (!pe_lkup)
            {
                SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NOT_EXIST);
            }

            SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_operate_key_field(lchip, pe_lkup, &key_field, 1));

            action_field.type = CTC_ACL_FIELD_ACTION_CP_TO_CPU;
            action_field.ext_data = &acl_to_cpu;
            acl_to_cpu.mode = CTC_ACL_TO_CPU_MODE_TO_CPU_NOT_COVER;
            acl_to_cpu.cpu_reason_id = CTC_PKT_CPU_REASON_DROP;

            SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_add_dsacl_field_wlan_error_to_cpu(lchip, &action_field, pe_lkup, 0, 1));
        }

        for (lport=0; lport<SYS_USW_MAX_PORT_NUM_PER_CHIP; lport++)
        {
            if (lport < SYS_INTERNAL_PORT_START)
            {
                gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);

                /*enable acl on ipe level 7*/
                acl_prop.acl_en = 1;
                acl_prop.tcam_lkup_type = CTC_ACL_TCAM_LKUP_TYPE_CID;
                acl_prop.direction = CTC_INGRESS;
                acl_prop.acl_priority = p_usw_acl_master[lchip]->igs_block_num -1;
                acl_prop.class_id = 2;

                SYS_USW_ACL_ERROR_RETURN_UNLOCK(sys_usw_port_api_set_acl_property(lchip, gport, &acl_prop));
            }
        }

        /*install acl group*/
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_install_group(lchip, SYS_ACL_GROUP_ID_DOT1AE_CRYPT_ERROR, NULL));

        p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu = 1;
    }
    else if ((!enable) && p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu)
    {
        for (lport=0; lport<SYS_USW_MAX_PORT_NUM_PER_CHIP; lport++)
        {
            if (lport < SYS_INTERNAL_PORT_START)
            {
                gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);

                /*enable acl on ipe level 7*/
                acl_prop.acl_en = 0;
                acl_prop.direction = CTC_INGRESS;
                acl_prop.acl_priority = p_usw_acl_master[lchip]->igs_block_num -1;

                SYS_USW_ACL_ERROR_RETURN_UNLOCK(sys_usw_port_api_set_acl_property(lchip, gport, &acl_prop));
            }
        }

        /* check if group exist */
        _sys_usw_acl_get_group_by_gid(lchip, SYS_ACL_GROUP_ID_DOT1AE_CRYPT_ERROR, &pg);
        if (pg)
        {
    		/*uninstall acl group*/
            SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_uninstall_group(lchip, SYS_ACL_GROUP_ID_DOT1AE_CRYPT_ERROR));

            /*remove all entry*/
            SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_remove_all_entry(lchip, SYS_ACL_GROUP_ID_DOT1AE_CRYPT_ERROR));

            /*destroy acl group*/
            SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_destroy_group(lchip, SYS_ACL_GROUP_ID_DOT1AE_CRYPT_ERROR));
        }

        p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu = 0;
    }

    if (p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu || p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu)
    {
        SetIpeFwdCtl(V, hardErrorDebugEn_f, &ipe_fwd, 1);
        cmd = DRV_IOW(IpeFwdCtl_t, DRV_ENTRY_FLAG);
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_fwd));

        SetIpeAclQosCtl(V, hardErrorDebugEn_f, &ipe_acl_qos_ctl, 1);
        cmd = DRV_IOW(IpeAclQosCtl_t, DRV_ENTRY_FLAG);
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_acl_qos_ctl));
    }
    else if ((!p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu) && (!p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu))
    {
        SetIpeFwdCtl(V, hardErrorDebugEn_f, &ipe_fwd, 0);
        cmd = DRV_IOW(IpeFwdCtl_t, DRV_ENTRY_FLAG);
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_fwd));

        SetIpeAclQosCtl(V, hardErrorDebugEn_f, &ipe_acl_qos_ctl, 0);
        cmd = DRV_IOW(IpeAclQosCtl_t, DRV_ENTRY_FLAG);
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &ipe_acl_qos_ctl));
    }

    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}
int32
sys_usw_acl_get_upa_en(uint8 lchip, uint8 dir, uint8* p_enable)
{
    CTC_PTR_VALID_CHECK(p_enable);
    SYS_ACL_INIT_CHECK();

    SYS_USW_ACL_LOCK(lchip);
    *p_enable = (SYS_USW_ACL_UPA_EN(lchip, dir)) ? 1:0;
    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}

uint32
sys_usw_acl_get_lkup_level_bmp(uint8 lchip, uint8 dir, uint8 block_id)
{
    uint32 lkup_level_bitmap = 0;

    /* !!Must not add acl lock, the func only called by stats when alloc stats_ptr, which only called by acl mode in acl lock */
    if(DRV_FROM_TMM(lchip) || SYS_USW_ACL_UPA_EN(lchip,dir))
    {
        CTC_BIT_SET(lkup_level_bitmap, block_id);
    }
    else
    {
        uint8 block_index = 0;
        block_index = (CTC_INGRESS == dir ? block_id: block_id + ACL_IGS_BLOCK_MAX_NUM);
        lkup_level_bitmap = p_usw_acl_master[lchip]->league[block_index].lkup_level_bitmap;
    }
    return lkup_level_bitmap;
}


#define _ACL_LEAGUE_

uint8
_sys_usw_acl_get_league_block(uint8 lchip, uint8 block_id, uint8 *block_list)
{
    sys_acl_league_t *p_league = NULL;
    uint8  loop = 0;
    uint8  block_cnt = 0;

    p_league = &p_usw_acl_master[lchip]->league[block_id];
    for (loop=0; loop<MCHIP_CAP(SYS_CAP_ACL_INGRESS_LKUP_NUM); loop++)
    {
        if (!CTC_IS_BIT_SET(p_league->lkup_level_bitmap, loop))
        {
            continue;
        }
        if (NULL != block_list)
        {
            block_list[block_cnt] = loop;
        }
        block_cnt++;
    }
    return block_cnt;
}

uint8
sys_usw_acl_get_league_block(uint8 lchip, uint8 block_id, uint8 *block_list)
{
    uint8  block_num = 0;
    SYS_USW_ACL_LOCK(lchip);
    block_num = _sys_usw_acl_get_league_block(lchip, block_id, block_list);
    SYS_USW_ACL_UNLOCK(lchip);
    return block_num;
}

STATIC void  _sys_usw_acl_league_free(void* val)
{
    sys_usw_acl_league_node_t* p_val = (sys_usw_acl_league_node_t*)val;
    if(val)
    {
        if(p_val->p_buffer)
        {
            mem_free(p_val->p_buffer);
        }
        mem_free(val);
    }
    return;
}
STATIC int32 _sys_usw_acl_league_cmp(void* val, void* val1)
{
    sys_usw_acl_league_node_t* p_val = (sys_usw_acl_league_node_t*)val;
    sys_usw_acl_league_node_t* p_val1 = (sys_usw_acl_league_node_t*)val1;

    if(p_val->prio > p_val1->prio)
    {
        return -1;
    }
    return 0;
}

int32
sys_usw_acl_set_league_mode(uint8 lchip, ctc_acl_league_t* league)
{
    int32 ret = 0;
    uint32 bmp = 0;
    uint32 tmp_bmp = 0;
    uint8 block_id = 0;
    uint8 tmp_block_id = 0;
    uint8 idx = 0;
    uint8 max_idx = 0;
    uint32 new_size = 0;
    uint32 new_count = 0;
    uint32 count = 0;
    uint32 cmd = 0;
    uint8 b_do_merge = FALSE;
    uint8 acl_max_block_num = 0;
    sys_acl_league_t* p_sys_league = NULL;
    sys_acl_league_t* p_tmp_league = NULL;
    ctc_fpa_entry_t** p_tmp_entries = NULL;
    ctc_global_acl_property_t acl_property;
    ctc_linklist_t* node_list[CTC_FPA_KEY_SIZE_NUM] = {NULL};
    uint8  key_size;
    uint8  step ;
    uint8  league_update_bmp = 0;
    uint8  sub_blk_cnt = 0;
    uint8  op_mode = 0;
    uint8  enable = 0;
    uint8  sub_blk[24] = {0};   /*sub blk range is 0~14*/
    uint16 sub_entry_num[CTC_FPA_KEY_SIZE_NUM] = {0};
    uint16 sub_free_num[CTC_FPA_KEY_SIZE_NUM] = {0};
    uint16 base = 0;
    sys_usw_acl_league_node_t** node_array = NULL;
    uint8  exist_short_key = 0;
    uint8  exist_no_short_key = 0;
    EpeAclLkpSelectTcamSlice_m lkup_select;

    SYS_ACL_DBG_FUNC();

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(league);
    acl_max_block_num = (CTC_INGRESS == league->dir ? ACL_IGS_BLOCK_MAX_NUM: ACL_EGS_BLOCK_MAX_NUM);
    CTC_MAX_VALUE_CHECK(league->acl_priority, acl_max_block_num - 1);
    if ((league->lkup_level_bitmap >> acl_max_block_num) != 0)
    {
        return CTC_E_INVALID_CONFIG;
    }

    if(league->auto_move_en && (SYS_USW_ACL_UPA_EN(lchip, league->dir)))
    {
        return CTC_E_INVALID_PARAM;
    }
    SYS_USW_ACL_LOCK(lchip);
    block_id = (CTC_INGRESS == league->dir ? league->acl_priority: league->acl_priority + ACL_IGS_BLOCK_MAX_NUM);
    if ( (CTC_INGRESS == league->dir && (DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip))) || DRV_FROM_AT(lchip) )
    {
        CTC_ERROR_RETURN_WITH_UNLOCK(MCHIP_ACL(lchip)->set_league_mode_flex(lchip, league, &sub_blk_cnt, sub_blk, &op_mode), p_usw_acl_master[lchip]->acl_mutex);
        league_update_bmp = (CTC_INGRESS == league->dir) ? p_usw_acl_master[lchip]->league_update_bmp : p_usw_acl_master[lchip]->egs_league_update_bmp;
        SYS_USW_ACL_UNLOCK(lchip);
        if (op_mode == SYS_ACL_LEAGUE_OP_NONE)
        {
            return CTC_E_NONE;
        }
        /*update port/vlan/interface/presel, port/vlan/interface no need per part enable*/
        enable = (op_mode==SYS_ACL_LEAGUE_OP_SET || op_mode==SYS_ACL_LEAGUE_OP_UPDATE) ? TRUE : FALSE;
        if (CTC_IS_BIT_SET(league_update_bmp, SYS_ACL_LEAGUE_UPDATE_PORT))
        {
            CTC_ERROR_RETURN(sys_usw_port_api_set_acl_league_property(lchip, block_id, enable, sub_blk_cnt, sub_blk));
        }
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_BLOCK, 1);
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MASTER, 1);
        return CTC_E_NONE;
    }

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"dir: %u,prio:%d,bitmap:0x%x, ext-tcam 0x%x\n", league->dir,league->acl_priority,league->lkup_level_bitmap, league->ext_tcam_bitmap);

    bmp = 0xFFFFFFFF;
    max_idx = (CTC_INGRESS == league->dir ? ACL_IGS_BLOCK_MAX_NUM: ACL_EGS_BLOCK_MAX_NUM);
    bmp = ((uint32)(bmp >> max_idx)) << max_idx;
    /*merge or cancel merge level can not bigger than max valid acl priority*/
    if (league->lkup_level_bitmap & bmp)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PARAM);
    }

    bmp = league->lkup_level_bitmap | (1<<league->acl_priority);
    p_sys_league = &(p_usw_acl_master[lchip]->league[block_id]);

    /*this level has been already merged*/
    if (p_sys_league->lkup_level_bitmap == 0)
    {
        ret = _sys_usw_acl_league_cancel_high_block(lchip, league);
        SYS_USW_ACL_UNLOCK(lchip);
        return ret;
    }

    /*MUST check parameter before expand tcam*/
    if (p_sys_league->lkup_level_bitmap != bmp)
    {
        for (idx=league->acl_priority+1; idx<max_idx; idx++)
        {
            if (CTC_IS_BIT_SET(bmp, idx) && (!CTC_IS_BIT_SET(bmp, idx-1)))
            {
                CTC_ERROR_GOTO(CTC_E_INVALID_PARAM, ret, end_1);
            }

            tmp_block_id = (CTC_INGRESS == league->dir ? idx: idx + ACL_IGS_BLOCK_MAX_NUM);
            p_tmp_league = &(p_usw_acl_master[lchip]->league[tmp_block_id]);

            /*merge block*/
            if (CTC_IS_BIT_SET(bmp, idx) && (!CTC_IS_BIT_SET(p_sys_league->lkup_level_bitmap, idx)))
            {
                /*block has already been merged*/
                tmp_bmp = p_tmp_league->lkup_level_bitmap;
                if (tmp_bmp == 0)
                {
                    CTC_ERROR_GOTO(CTC_E_INVALID_PARAM, ret, end_1);
                }
                /*block has already merged others*/
                CTC_BIT_UNSET(tmp_bmp,idx);
                if (tmp_bmp != 0)
                {
                    ret = _sys_usw_acl_league_merge_high_block(lchip, league, idx);
                    SYS_USW_ACL_UNLOCK(lchip);
                    return ret;
                }
                if((!league->auto_move_en) && (p_usw_acl_master[lchip]->block[tmp_block_id].fpab.entry_count != p_usw_acl_master[lchip]->block[tmp_block_id].fpab.free_count))
                {
                    ret = _sys_usw_acl_league_merge_high_block(lchip, league, idx);
                    SYS_USW_ACL_UNLOCK(lchip);
                    return ret;
                }
            }
            /*cancel merge block*/
            else if (!CTC_IS_BIT_SET(bmp, idx) && (CTC_IS_BIT_SET(p_sys_league->lkup_level_bitmap, idx)))
            {
                CTC_ERROR_GOTO(_sys_usw_acl_get_entry_count_on_lkup_level(lchip, block_id, idx, &count), ret, end_1);
                /*level not empty*/
                if (count)
                {
                    CTC_ERROR_GOTO(CTC_E_INVALID_PARAM, ret, end_1);
                }
            }
        }
    }

    /*expand tcam firstly*/
    if(league->ext_tcam_bitmap)
    {
        if(!DRV_IS_TSINGMA(lchip) || league->dir == CTC_EGRESS)
        {
            CTC_ERROR_GOTO(CTC_E_NOT_SUPPORT, ret, end_1);
        }
        SYS_USW_ACL_ERROR_RETURN_UNLOCK(_sys_usw_acl_adjust_ext_tcam(lchip, league->ext_tcam_bitmap));
    }

    /*nothing changed*/
    if (p_sys_league->lkup_level_bitmap == bmp)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NONE);
    }

    max_idx = (CTC_INGRESS == league->dir ? ACL_IGS_BLOCK_MAX_NUM: ACL_EGS_BLOCK_MAX_NUM);
    new_count = SYS_ACL_BLOCK(lchip, block_id).fpab.entry_count;

    sal_memset(&acl_property, 0, sizeof(acl_property));
    acl_property.dir = league->dir;

    tmp_block_id = (CTC_INGRESS == league->dir ? league->acl_priority: league->acl_priority + ACL_IGS_BLOCK_MAX_NUM);

    /*create temp entry list and traverse the first block*/
    if(league->auto_move_en)
    {
        MALLOC_ZERO(MEM_ACL_MODULE, node_array, SYS_ACL_MAX_TCAM_IDX_NUM*sizeof(sys_usw_acl_league_node_t*));
        if(NULL == node_array)
        {
            CTC_ERROR_GOTO(CTC_E_NO_MEMORY, ret, end_1);
        }
        for(key_size=CTC_FPA_KEY_SIZE_80; key_size < CTC_FPA_KEY_SIZE_NUM; key_size++)
        {
            node_list[key_size] = ctc_list_create(_sys_usw_acl_league_cmp, _sys_usw_acl_league_free);
            if(NULL == node_list[key_size])
            {
                ret = CTC_E_NO_MEMORY;
                goto end_1;
            }
        }
        CTC_ERROR_GOTO(_sys_usw_acl_league_traverse_block(lchip, tmp_block_id, &base, (ctc_linklist_t**)node_list, \
            (uint16*)sub_entry_num, (uint16*)sub_free_num, node_array), ret, end_1);
        if(node_list[CTC_FPA_KEY_SIZE_80]->count)
        {
            exist_short_key = 1;
        }
        if(node_list[CTC_FPA_KEY_SIZE_160]->count || node_list[CTC_FPA_KEY_SIZE_320]->count || node_list[CTC_FPA_KEY_SIZE_640]->count)
        {
            exist_no_short_key = 1;
        }
    }
    for (idx=league->acl_priority+1; idx<max_idx; idx++)
    {
        tmp_block_id = (CTC_INGRESS == league->dir ? idx: idx + ACL_IGS_BLOCK_MAX_NUM);
        p_tmp_league = &(p_usw_acl_master[lchip]->league[tmp_block_id]);

        acl_property.lkup_level = idx;
        CTC_ERROR_GOTO(sys_usw_get_glb_acl_property(lchip, &acl_property, 1), ret, end_1);
        /*merge block*/
        if (CTC_IS_BIT_SET(bmp, idx) && (!CTC_IS_BIT_SET(p_sys_league->lkup_level_bitmap, idx)))
        {
            if(league->auto_move_en)
            {
                CTC_ERROR_GOTO(_sys_usw_acl_league_traverse_block(lchip, tmp_block_id, &base, (ctc_linklist_t**)node_list, \
                    (uint16*)sub_entry_num, (uint16*)sub_free_num, node_array), ret, end_1);
                if(node_list[CTC_FPA_KEY_SIZE_80]->count)
                {
                    exist_short_key = 1;
                }
                if(node_list[CTC_FPA_KEY_SIZE_160]->count || node_list[CTC_FPA_KEY_SIZE_320]->count || node_list[CTC_FPA_KEY_SIZE_640]->count)
                {
                    exist_no_short_key = 1;
                }
                if(exist_short_key && exist_no_short_key)
                {
                    ret = CTC_E_INVALID_PARAM;
                    goto end_1;
                }
            }
            else if (SYS_ACL_BLOCK(lchip, tmp_block_id).fpab.entry_count != SYS_ACL_BLOCK(lchip, tmp_block_id).fpab.free_count)
            {
                ret = CTC_E_INVALID_PARAM;
                goto end_1;
            }

            b_do_merge = TRUE;
            new_count += SYS_ACL_BLOCK(lchip, tmp_block_id).entry_num;
            acl_property.random_log_pri = league->acl_priority;


        }
        /*cancel merge block*/
        else if (!CTC_IS_BIT_SET(bmp, idx) && (CTC_IS_BIT_SET(p_sys_league->lkup_level_bitmap, idx)))
        {
            CTC_ERROR_GOTO(_sys_usw_acl_get_entry_count_on_lkup_level(lchip, block_id, idx, &count), ret, end_1);
            /*level not empty*/
            if (count)
            {
                ret = CTC_E_INVALID_PARAM;
                goto end_1;
            }
            acl_property.random_log_pri = idx;
        }
        CTC_ERROR_GOTO(sys_usw_set_glb_acl_property(lchip, &acl_property, 1), ret, end_1);
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_BLOCK, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_GROUP, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY, 1);

    /*write reg*/
    ret = _sys_usw_acl_set_league_table(lchip, league);
    if (ret)
    {
       goto end_1;
    }

    /*update SW table*/
    cmd = DRV_IOR(EpeAclLkpSelectTcamSlice_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &lkup_select);
    if (b_do_merge)
    {
        new_size = sizeof(ctc_fpa_entry_t*) * new_count;
        MALLOC_ZERO(MEM_ACL_MODULE, p_tmp_entries, new_size);
        if (NULL == p_tmp_entries)
        {
            ret = CTC_E_NO_MEMORY;
            goto end_1;
        }
        if(league->auto_move_en)
        {
            /*1. update merged block DB*/
            uint16 total_free_num = 0;
            uint16 start_offset = 0;
            uint16 temp_cnt = 0;
            step = 1;

            temp_cnt = SYS_ACL_BLOCK(lchip, block_id).fpab.entry_count;
            mem_free(SYS_ACL_BLOCK(lchip, block_id).fpab.entries);
            sal_memset(&(SYS_ACL_BLOCK(lchip, block_id).fpab),0, sizeof(ctc_fpa_block_t)) ;
            for(key_size=CTC_FPA_KEY_SIZE_80; key_size < CTC_FPA_KEY_SIZE_NUM; key_size++)
            {
                SYS_ACL_BLOCK(lchip, block_id).fpab.start_offset[key_size] = start_offset;
                SYS_ACL_BLOCK(lchip, block_id).fpab.sub_entry_count[key_size] = sub_entry_num[key_size];
                SYS_ACL_BLOCK(lchip, block_id).fpab.sub_free_count[key_size] = sub_free_num[key_size];
                SYS_ACL_BLOCK(lchip, block_id).fpab.sub_rsv_count[key_size] = 0;
                total_free_num += sub_free_num[key_size]*step;
                start_offset += sub_entry_num[key_size]*step;
                step *= 2;
            }
            SYS_ACL_BLOCK(lchip, block_id).fpab.free_count = total_free_num;
            SYS_ACL_BLOCK(lchip, block_id).fpab.entry_count = temp_cnt;
            SYS_ACL_BLOCK(lchip, block_id).fpab.part_num = 1;
        }
        else
        {
            uint32 old_size = 0;
            old_size = sizeof(sys_acl_entry_t*) * SYS_ACL_BLOCK(lchip, block_id).fpab.entry_count;
            sal_memcpy(p_tmp_entries, SYS_ACL_BLOCK(lchip, block_id).fpab.entries, old_size);

            mem_free(SYS_ACL_BLOCK(lchip, block_id).fpab.entries);
            SYS_ACL_BLOCK(lchip, block_id).fpab.entries = p_tmp_entries;
        }
        /*2. merge block*/
        for (idx = league->acl_priority + 1; idx < max_idx; idx++)
        {
            tmp_block_id = (CTC_INGRESS == league->dir ? idx: idx + ACL_IGS_BLOCK_MAX_NUM);
            p_tmp_league = &(p_usw_acl_master[lchip]->league[tmp_block_id]);

            if (CTC_IS_BIT_SET(bmp, idx) && (!CTC_IS_BIT_SET(p_sys_league->lkup_level_bitmap, idx)))
            {
                _sys_usw_acl_set_league_merge(lchip, p_sys_league, p_tmp_league, league->auto_move_en);
            }

        }

        /*3. move entry from old index to new index and update associated SW table*/
        if(league->auto_move_en)
        {
            CTC_ERROR_GOTO(_sys_usw_acl_league_move_entry(lchip, (ctc_linklist_t**)node_list, p_tmp_entries, \
                (uint16*)sub_entry_num, league->acl_priority, node_array), ret, end_1);
        }
        SYS_ACL_BLOCK(lchip, block_id).fpab.entries = p_tmp_entries;
        if (DRV_FROM_TMM(lchip) && league->dir == CTC_EGRESS)
        {
            SetEpeAclLkpSelectTcamSlice(V, gAclLkpLevel_0_selectTcamSliceBitmap_f+league->acl_priority, &lkup_select, bmp);
        }
    }
    else
    { /*cancel block */

        for (idx = max_idx - 1; idx > league->acl_priority; idx--)
        {
            tmp_block_id = (CTC_INGRESS == league->dir ? idx: idx + ACL_IGS_BLOCK_MAX_NUM);
            p_tmp_league = &(p_usw_acl_master[lchip]->league[tmp_block_id]);

            if (!CTC_IS_BIT_SET(bmp, idx) && (CTC_IS_BIT_SET(p_sys_league->lkup_level_bitmap, idx)))
            {

                if (DRV_FROM_TMM(lchip) && league->dir == CTC_EGRESS)
                {
                    SetEpeAclLkpSelectTcamSlice(V, gAclLkpLevel_0_selectTcamSliceBitmap_f+idx, &lkup_select, (1<<idx));
                }
                _sys_usw_acl_set_league_cancel(lchip, p_sys_league, p_tmp_league);
            }
        }
        new_size = sizeof(ctc_fpa_entry_t*) * SYS_ACL_BLOCK(lchip, block_id).fpab.entry_count;
        MALLOC_ZERO(MEM_ACL_MODULE, p_tmp_entries, new_size);
        if ((NULL == p_tmp_entries) && new_size)
        {
            ret = CTC_E_NO_MEMORY;

            goto end_1;
        }
        sal_memcpy(p_tmp_entries, SYS_ACL_BLOCK(lchip, block_id).fpab.entries, new_size);
        mem_free(SYS_ACL_BLOCK(lchip, block_id).fpab.entries);
        SYS_ACL_BLOCK(lchip, block_id).fpab.entries = p_tmp_entries;
        if (DRV_FROM_TMM(lchip) && league->dir == CTC_EGRESS)
        {
            SetEpeAclLkpSelectTcamSlice(V, gAclLkpLevel_0_selectTcamSliceBitmap_f+league->acl_priority, &lkup_select, bmp);
        }
    }
    cmd = DRV_IOW(EpeAclLkpSelectTcamSlice_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &lkup_select);

end_1:
    SYS_USW_ACL_UNLOCK(lchip);
    for(key_size=CTC_FPA_KEY_SIZE_80; key_size < CTC_FPA_KEY_SIZE_NUM; key_size++)
    {
        if(node_list[key_size])
        {
            ctc_list_delete_all_node(node_list[key_size]);
            ctc_list_free(node_list[key_size]);
        }
    }
    if(node_array)
    {
        mem_free(node_array);
    }
    return ret;
}

int32
sys_usw_acl_get_league_mode(uint8 lchip, ctc_acl_league_t* league)
{
    uint8 block_id = 0;
    int32 ret = 0;
    sys_acl_league_t* p_sys_league = NULL;


    SYS_ACL_DBG_FUNC();

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(league);
    CTC_MAX_VALUE_CHECK(league->acl_priority, (CTC_INGRESS == league->dir ? ACL_IGS_BLOCK_MAX_NUM-1: ACL_EGS_BLOCK_MAX_NUM-1));
    SYS_USW_ACL_LOCK(lchip);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"sys_usw_acl_get_league_mode,dir:%u,prio:%d \n", league->dir,league->acl_priority);

    block_id = (CTC_INGRESS == league->dir ? league->acl_priority: league->acl_priority + ACL_IGS_BLOCK_MAX_NUM);
    p_sys_league = &(p_usw_acl_master[lchip]->league[block_id]);
    league->lkup_level_bitmap = p_sys_league->lkup_level_bitmap;
    league->size = p_sys_league->size;

    if(p_sys_league->merged_to == p_sys_league->hdr_block_id &&  league->lkup_level_bitmap && league->list_cnt && league->leagued_list && DRV_FROM_TMM(lchip))
    {
        ret = _sys_usw_acl_get_ordered_league_block(lchip, block_id, p_sys_league->size, league);
    }
    else
    {
        league->list_cnt = 0;
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_reorder_entry(uint8 lchip, ctc_acl_reorder_t* reorder)
{
    int32 ret = 0;
    uint8 block_id = 0;
    sys_acl_league_t* p_sys_league = NULL;

    SYS_ACL_DBG_FUNC();

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(reorder);
    CTC_MAX_VALUE_CHECK(reorder->acl_priority, (CTC_INGRESS == reorder->dir ? ACL_IGS_BLOCK_MAX_NUM-1: ACL_EGS_BLOCK_MAX_NUM-1));

    if (DRV_FROM_TMM(lchip) && reorder->mode == CTC_ACL_REORDER_MODE_SCATTER)
    {
        return CTC_E_NOT_SUPPORT;
    }
    if (SYS_USW_ACL_UPA_EN(lchip, reorder->dir))
    {
        return CTC_E_NOT_SUPPORT;
    }
    if (((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && CTC_INGRESS == reorder->dir) || DRV_FROM_AT(lchip))
    {
        return MCHIP_ACL(lchip)->reorder_entry(lchip, reorder);
    }
    SYS_USW_ACL_LOCK(lchip);

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"sys_usw_acl_reorder_entry,mode:%u,dir:%u,prio:%d \n", reorder->mode,reorder->dir,reorder->acl_priority);

    block_id = (CTC_INGRESS == reorder->dir ? reorder->acl_priority: reorder->acl_priority + ACL_IGS_BLOCK_MAX_NUM);
    p_sys_league = &(p_usw_acl_master[lchip]->league[block_id]);

    /*acl priority'lookup level is empty*/
    if (!p_sys_league->lkup_level_bitmap)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NONE);
    }

    /*no entry*/
    if (p_usw_acl_master[lchip]->block[p_sys_league->block_id].fpab.entry_count == p_usw_acl_master[lchip]->block[p_sys_league->block_id].fpab.free_count)
    {
        SYS_USW_ACL_RETURN_UNLOCK(CTC_E_NONE);
    }

    switch (reorder->mode)
    {
        case CTC_ACL_REORDER_MODE_SCATTER:
        {
            ret = _sys_usw_acl_reorder_entry_scatter(lchip, p_sys_league);
            break;
        }
        case CTC_ACL_REORDER_MODE_DOWNTOUP:
        {
            ret = _sys_usw_acl_reorder_entry_down_to_up(lchip, p_sys_league);
            break;
        }
        case CTC_ACL_REORDER_MODE_UPTODOWN:
        {
            ret = _sys_usw_acl_reorder_entry_up_to_down(lchip, p_sys_league);
            break;
        }
        default :
        {
            SYS_USW_ACL_RETURN_UNLOCK(CTC_E_INVALID_PARAM);
        }
    }

    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_replace_block(uint8 lchip, ctc_acl_replace_t* p_replace)
{
    int32 ret = 0;

    SYS_ACL_DBG_FUNC();

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_replace);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"  src lookup level %u, dst lookup leve %u\n", p_replace->src_lkup_level, p_replace->dest_lkup_level);

    if (p_replace->dir == CTC_EGRESS)
    {
        if(!DRV_FROM_AT(lchip))
        {
            return CTC_E_NOT_SUPPORT;
        }
        CTC_MAX_VALUE_CHECK(p_replace->src_lkup_level, ACL_EGS_BLOCK_MAX_NUM-1);
        CTC_MAX_VALUE_CHECK(p_replace->dest_lkup_level, ACL_EGS_BLOCK_MAX_NUM-1);
    }
    else
    {
        CTC_MAX_VALUE_CHECK(p_replace->src_lkup_level, ACL_IGS_BLOCK_MAX_NUM-1);
        CTC_MAX_VALUE_CHECK(p_replace->dest_lkup_level, ACL_IGS_BLOCK_MAX_NUM-1);
    }

    if(NULL == MCHIP_ACL(lchip)->replace_block)
    {
        return CTC_E_NOT_SUPPORT;
    }
    SYS_USW_ACL_LOCK(lchip);
    ret = MCHIP_ACL(lchip)->replace_block(lchip, p_replace);
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

#define __ACL_LKUP_PP_DISABLE__


int32
sys_usw_acl_get_pp_en_lkup_property(uint8 lchip, uint8 dir, uint8 priority, uint8 *global_pp_en)
{
    SYS_ACL_INIT_CHECK();

    CTC_PTR_VALID_CHECK(global_pp_en);

    if(0xff == priority)
    {
        *global_pp_en = 0;
        return CTC_E_NONE;
    }

    if(lchip == SYS_PP_BASE(lchip))
    {
        *global_pp_en = (p_usw_acl_master[lchip]->global_pp_en_bmp[dir] >> priority) & 0x01;

    }

    return CTC_E_NONE;
}
uint32
sys_usw_acl_get_lkup_pp_en_bmp(uint8 lchip, uint8 dir)
{
    SYS_ACL_INIT_CHECK();

    if(lchip == SYS_PP_BASE(lchip))
    {
          return p_usw_acl_master[lchip]->global_pp_en_bmp[dir];
    }

    return 0;
}

int32
sys_usw_acl_check_league_block_valid(uint8 lchip, ctc_acl_league_t* league, uint32 global_pp_en_bmp)
{
    uint8  block_base       = 0;
    uint8  max_block_num    = 0;
    uint8  index            = 0;
    uint8 global_pp_en      = league->global_pp_en;
    sys_acl_block_t * pb    = NULL;
    uint32 block_bmp        = 0;
    uint16 pp_bmp = SYS_PP_BMP_MAPPING(league->pp_bmp);

    SYS_ACL_DBG_FUNC();

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(league);

    max_block_num = (CTC_INGRESS == league->dir ? ACL_IGS_BLOCK_MAX_NUM: ACL_EGS_BLOCK_MAX_NUM);
    block_bmp = league->lkup_level_bitmap;
    block_base = league->dir==CTC_INGRESS?0:ACL_IGS_BLOCK_MAX_NUM;

    /* check block valid */
    do
    {
        if(global_pp_en)
        {
            /* is global acl block, continue, because global block check will do later */
            if(!CTC_IS_BIT_SET(block_bmp, index) || CTC_IS_BIT_SET(global_pp_en_bmp, index))
            {
                index++;
                continue;
            }
        }
        else
        {
            /* is not global acl block, continue */
            if(!CTC_IS_BIT_SET(block_bmp, index) || !CTC_IS_BIT_SET(global_pp_en_bmp, index))
            {
                index++;
                continue;
            }
            if(pp_bmp != 0xff)
            {
                SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "block(%d) is global lkup, if unset global lkup, the pp_bmp must be 0xff, current is 0x%x!!!\n", index, pp_bmp);
                return CTC_E_INVALID_CONFIG;
            }
        }

        /* check the block status */
        pb = &SYS_ACL_BLOCK(lchip, index+block_base);
        if(!BLOCK_EMPTY(pb, 0))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "global lkup:%d, pp:%d, block: %u has entry\n", global_pp_en, lchip, index+block_base);
            return CTC_E_IN_USE;
        }

        if (pb->block_status == SYS_ACL_BLOCK_STATUS_MERGE_SRC)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "global lkup:%d, pp:%d, block: %u has been leagued\n", global_pp_en, lchip, index+block_base);
            return CTC_E_IN_USE;
        }

        if (!ctc_list_isempty(pb->group_list))
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "global lkup:%d, pp:%d, block: %u has group\n", global_pp_en, lchip, index+block_base);
            return CTC_E_IN_USE;
        }

        index++;

    }while(index < max_block_num);

    return CTC_E_NONE;
}

int32
sys_usw_acl_get_sys_group_info_by_gid(uint8 lchip, uint32 group_id, ctc_direction_t *dir, uint8 *priority)
{
    sys_acl_group_t* pg_lkup = NULL;
    uint8 pp_base   = SYS_PP_BASE(lchip);

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(dir);
    CTC_PTR_VALID_CHECK(priority);

    SYS_ACL_CHECK_GROUP_ID(group_id);

    /* if hash group, returns */
    if (group_id > CTC_ACL_GROUP_ID_NORMAL)
    {
        *dir = CTC_INGRESS;
        *priority = 0xff;
        return CTC_E_NONE;
    }
    SYS_USW_ACL_LOCK(lchip);
    /* check sys group, if group not exist return*/
    _sys_usw_acl_get_group_by_gid(pp_base, group_id, &pg_lkup);
    if (!pg_lkup)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }

    *dir = pg_lkup->group_info.dir;
    *priority = (CTC_ACL_GROUP_TYPE_HASH == pg_lkup->group_info.type) ? 0xff : pg_lkup->group_info.block_id;
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_acl_get_sys_group_info_by_eid(uint8 lchip, uint32 entry_id, ctc_direction_t *dir, uint8 *priority)
{
    sys_acl_entry_t* pe_lkup = NULL;
    uint16 pp_bmp   = 0;
    uint8 pp_id     = 0;
    uint8 pp_base   = SYS_PP_BASE(lchip);
    uint8 pp_num    = SYS_PP_NUM(lchip);

    SYS_ACL_INIT_CHECK();

    CTC_PTR_VALID_CHECK(dir);
    CTC_PTR_VALID_CHECK(priority);

    if(!MCHIP_FEATURE_PP_EN(lchip, CTC_FEATURE_ACL))
    {
        pp_bmp = 0x01;
        pp_num = 1;
    }
    else
    {
        SYS_ACL_ENTRY_HASH_ENTRY_EXIST(lchip, SYS_COM_ENTRY_HASH_ACL_ENTRY, entry_id, pp_bmp);
    }
    SYS_USW_ACL_LOCK(lchip);
    /* get pp_id from group_id */
    for (pp_id=pp_base; pp_id<pp_base+pp_num; pp_id++)
    {
        if (!CTC_IS_BIT_SET(pp_bmp, pp_id-pp_base))
        {
            continue;
        }

        /* check sys group, if group not exist return*/
        _sys_usw_acl_get_entry_by_eid(pp_id, entry_id, &pe_lkup);
        if (!pe_lkup)
        {
            SYS_USW_ACL_UNLOCK(lchip);
            return CTC_E_NOT_EXIST;
        }

        *dir = pe_lkup->group->group_info.dir;
        *priority = (CTC_ACL_GROUP_TYPE_HASH == pe_lkup->group->group_info.type) ? 0xff : pe_lkup->group->group_info.block_id;
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

#define _ACL_WB_
extern int32
  _sys_usw_acl_udf_rebuild_buffer_from_hw(uint8 lchip,  sys_acl_udf_entry_t  *p_sys_udf_entry);
/*
*  bridf  sync the acl entrys' stats-ptr, witch is not use the same ramid as block_id in stats, to the same ramid as the block_id.
*/
int32
sys_usw_acl_reorder_stats(uint8 lchip, ctc_acl_reorder_t* p_reorder, uint32* fail_list, uint32* fail_cnt)
{
    int32 ret = 0;
    sys_acl_block_t* pb = NULL;
    sys_acl_league_t* p_league = NULL;
    uint8 blk_idx = 0;
    uint8 new_acl_priority = 0;
    uint8 record = 0;
    uint32 loop = 0;
    sys_acl_entry_t* pe = NULL;
    sys_stats_acl_change_t stats_change;
    uint32 real_cnt = 0;
    uint32 stats_id = 0;

    SYS_ACL_DBG_FUNC();
    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_reorder);
    CTC_MAX_VALUE_CHECK(p_reorder->dir, CTC_BOTH_DIRECTION - 1);
    SYS_ACL_CHECK_GROUP_PRIO(p_reorder->dir, p_reorder->acl_priority);

    if(((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && p_reorder->dir == CTC_INGRESS)
       || DRV_FROM_AT(lchip))
    {
        return CTC_E_NONE;
    }

    SYS_USW_ACL_LOCK(lchip);
    blk_idx = (CTC_INGRESS == p_reorder->dir ? p_reorder->acl_priority: p_reorder->acl_priority + ACL_IGS_BLOCK_MAX_NUM);
    p_league = &(p_usw_acl_master[lchip]->league[blk_idx]);
    /* get league header block_id */
    if(p_league->lkup_level_bitmap == 0)
    {
        blk_idx = (CTC_INGRESS == p_reorder->dir ? p_league->merged_to : p_league->merged_to + ACL_IGS_BLOCK_MAX_NUM);
        new_acl_priority = p_league->merged_to;
    }
    else
    {
        new_acl_priority = p_reorder->acl_priority;
    }
    pb = &SYS_ACL_BLOCK(lchip, blk_idx);
    if(pb->fpab.entry_count == pb->fpab.free_count)
    {
        goto exit;
    }

    record = (fail_list && fail_cnt) ? 1 : 0;
    for(loop = 0; loop < pb->fpab.entry_count; loop++)
    {
        if(!pb->fpab.entries[loop])
        {
            continue;
        }
        pe = _ctc_container_of(pb->fpab.entries[loop], sys_acl_entry_t, fpae);
        SYS_ACL_GET_STATS_ID(stats_id, pe)
        if(!stats_id)
        {
            continue;
        }
        if((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
        {
            new_acl_priority = blk_idx;
            ACL_MAP_FLOW_STATS_BLOCK_ID0(pe, new_acl_priority);
        }

        stats_change.cb = _sys_usw_acl_change_stats_ptr_cb;
        stats_change.user_data = (void*)pe;
        stats_change.stats_id = stats_id;
        stats_change.new_block_id = new_acl_priority;
        ret = ret ? ret : sys_usw_flow_stats_change_acl_statsptr(lchip, &stats_change);
        if(ret && record)
        {
            if(real_cnt < *fail_cnt)
            {
                fail_list[real_cnt] = pe->fpae.entry_id;
            }
            real_cnt++;
        }
    }
    if(fail_cnt)
    {
        *fail_cnt = real_cnt;
    }

exit:
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}


#define _ACL_WB_
extern int32
  _sys_usw_acl_udf_rebuild_buffer_from_hw(uint8 lchip,  sys_acl_udf_entry_t  *p_sys_udf_entry);
int32
sys_usw_acl_wb_sync(uint8 lchip,uint32 app_id)
{
    int32 ret = CTC_E_NONE;
    int32 loop = 0;
    int32 loop_j = 0;
    uint8 acl_max_block_num = 0;
    sys_wb_acl_master_t* p_wb_acl_master = NULL;
    sys_wb_acl_block_t* p_wb_block = NULL;
    sys_wb_acl_lt_block_t* p_wb_lt_block = NULL;
    sys_acl_block_t*    p_acb = NULL;
    sys_acl_lt_block_t* p_ltb = NULL;
    ctc_wb_data_t wb_data = {0};
    sys_acl_traverse_data_t  user_data = {0};

    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);
    SYS_USW_ACL_LOCK(lchip);
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY )
    {
        /*sync acl entry*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_tcam_entry_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY);
        user_data.data0 = (void*)&wb_data;
        user_data.value0 = lchip;
        CTC_ERROR_GOTO(ctc_hash_traverse(p_usw_acl_master[lchip]->entry, _sys_usw_acl_wb_sync_tcam_entry, (void*) (&user_data)), ret, done);

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_HASH_ENTRY )
    {
        /*sync acl entry*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_hash_entry_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_HASH_ENTRY);
        user_data.data0 = (void*)&wb_data;
        user_data.value0 = lchip;
        CTC_ERROR_GOTO(ctc_hash_traverse(p_usw_acl_master[lchip]->entry, _sys_usw_acl_wb_sync_hash_entry, (void*) (&user_data)), ret, done);

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_HASH_ENTRY);
    }


    if (MCHIP_ACL(lchip)->wb_sync)
    {
        CTC_ERROR_GOTO(MCHIP_ACL(lchip)->wb_sync(lchip, app_id, &wb_data, &user_data), ret, done);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_MASTER)
    {
        /*sync acl_master */
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_master_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MASTER);

        p_wb_acl_master = (sys_wb_acl_master_t*)wb_data.buffer;
        p_wb_acl_master->lchip = lchip;
        p_wb_acl_master->version = SYS_WB_VERSION_ACL;
        p_wb_acl_master->sort_mode = p_usw_acl_master[lchip]->upa_en;
        p_wb_acl_master->league_update_bmp = p_usw_acl_master[lchip]->league_update_bmp;
        p_wb_acl_master->egs_league_update_bmp = p_usw_acl_master[lchip]->egs_league_update_bmp;
        p_wb_acl_master->glb_presel_en = p_usw_acl_master[lchip]->glb_presel_en;
        p_wb_acl_master->srv6_rsv_udf_idx = p_usw_acl_master[lchip]->srv6_rsv_udf_idx;
        p_wb_acl_master->global_pp_en_bmp[0] = p_usw_acl_master[lchip]->global_pp_en_bmp[0];
        p_wb_acl_master->global_pp_en_bmp[1] = p_usw_acl_master[lchip]->global_pp_en_bmp[1];

        for (loop = 0; loop < SYS_ACL_HASH_KEY_TYPE_NUM; loop++)
        {
            for (loop_j = 0; loop_j < SYS_ACL_HASH_SEL_PROFILE_MAX; loop_j++)
            {
                sal_memcpy((uint8*)&p_wb_acl_master->hash_sel_key_union_filed[loop][loop_j], &p_usw_acl_master[lchip]->hash_sel_key_union_filed[loop][loop_j], sizeof(sys_hash_sel_field_union_t));
            }
        }
        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MASTER);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_GROUP)
    {
        /*sync acl group*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_group_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_GROUP);
        CTC_ERROR_GOTO(ctc_hash_traverse(p_usw_acl_master[lchip]->group, _sys_usw_acl_wb_sync_group, (void*) (&wb_data)), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_GROUP);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_TCAM_CID)
    {
         CTC_WB_INIT_DATA_T((&wb_data), sys_wb_ofb_t,CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_CID);
        CTC_ERROR_GOTO(sys_usw_ofb_wb_sync(lchip, p_usw_acl_master[lchip]->ofb_type_cid,
                                           CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_CID, &wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_CID);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_BLOCK)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_block_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_BLOCK);
        for(loop=0; loop < ACL_IGS_BLOCK_MAX_NUM + ACL_EGS_BLOCK_MAX_NUM; loop++)
        {
            p_acb = &p_usw_acl_master[lchip]->block[loop];
            p_wb_block = (sys_wb_acl_block_t*)((uint8*)wb_data.buffer + wb_data.valid_cnt*sizeof(sys_wb_acl_block_t));

            p_wb_block->block_id = loop;
            p_wb_block->block_status = p_acb->block_status;
            p_wb_block->valid = p_acb->valid;

            p_wb_block->expand_blk_id = p_acb->expand_blk_id;
            p_wb_block->entry_num = p_acb->entry_num;
            p_wb_block->prev_block = p_acb->prev? p_acb->prev->block_id : 0xFF;
            p_wb_block->next_block = p_acb->next? p_acb->next->block_id : 0xFF;
            p_wb_block->same_size = p_acb->fpab.same_size;
            p_wb_block->part = p_acb->fpab.part;
            p_wb_block->part_num = p_acb->fpab.part_num;
            p_wb_block->entry_count = p_acb->fpab.entry_count;
            p_wb_block->fpa_block_base = p_acb->fpab.base;
            p_wb_block->vblock_entry_count = 0;
            sal_memcpy(p_wb_block->start_offset, p_acb->fpab.start_offset, sizeof(uint16)*CTC_FPA_KEY_SIZE_NUM);
            sal_memcpy(p_wb_block->sub_entry_count, p_acb->fpab.sub_entry_count, sizeof(uint16)*CTC_FPA_KEY_SIZE_NUM);
            sal_memcpy(p_wb_block->lkup_level_start, p_usw_acl_master[lchip]->league[loop].lkup_level_start, sizeof(uint16)*ACL_IGS_BLOCK_MAX_NUM);
            sal_memcpy(p_wb_block->lkup_level_count, p_usw_acl_master[lchip]->league[loop].lkup_level_count, sizeof(uint16)*ACL_IGS_BLOCK_MAX_NUM);
            p_wb_block->lkup_level_bitmap = p_usw_acl_master[lchip]->league[loop].lkup_level_bitmap & 0xFFFF;
            p_wb_block->lkup_level_bitmap_high = p_usw_acl_master[lchip]->league[loop].lkup_level_bitmap >> 16;
            p_wb_block->merged_to = p_usw_acl_master[lchip]->league[loop].merged_to;
            p_wb_block->size = p_usw_acl_master[lchip]->league[loop].size;
            p_wb_block->hdr_block = p_usw_acl_master[lchip]->league[loop].hdr_block_id;
            p_wb_block->rsv[0] = 0;
            p_wb_block->rsv[1] = 0;
            p_wb_block->rsv1 = 0;
            if (p_acb->fpab.vblock)
            {
                p_wb_block->vblock_entry_count = p_acb->fpab.vblock->entry_count;
                p_wb_block->vblock_sub_entry_count = p_acb->fpab.vblock->sub_entry_count[CTC_FPA_KEY_SIZE_160];
                SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO,"wb sync - block id: %u, vblock entry count :%u \n", loop, p_wb_block->vblock_entry_count);
            }
            wb_data.valid_cnt++;
        }

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_BLOCK);
    }

    if ((app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_LT_BLOCK) && DRV_FROM_TMM(lchip))
    {
        acl_max_block_num = DRV_FROM_AT(lchip) ? ACL_IGS_BLOCK_MAX_NUM + ACL_EGS_BLOCK_MAX_NUM : ACL_IGS_BLOCK_MAX_NUM;
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_lt_block_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_LT_BLOCK);
        for(loop=0; loop < acl_max_block_num; loop++)
        {
            p_ltb = &p_usw_acl_master[lchip]->lt_block[loop];
            p_wb_lt_block = (sys_wb_acl_lt_block_t*)((uint8*)wb_data.buffer + wb_data.valid_cnt*sizeof(sys_wb_acl_lt_block_t));

            p_wb_lt_block->block_id = loop;
            /*p_wb_lt_block->valid = p_ltb->valid;*/

            p_wb_lt_block->entry_valid = p_ltb->entry_valid;
            p_wb_lt_block->is_key160 = p_ltb->is_key160;
            p_wb_lt_block->ltid_bitmap = p_ltb->ltid_bitmap;

            p_wb_lt_block->entry_count = p_ltb->fpab.entry_count;
            p_wb_lt_block->start_offset = p_ltb->fpab.start_offset[0];
            p_wb_lt_block->rsv[0] = 0;
            p_wb_lt_block->rsv[1] = 0;

            wb_data.valid_cnt++;
        }

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_LT_BLOCK);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_UDF_ENTRY)
    {
        /*sync udf entry*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_udf_entry_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_UDF_ENTRY);
        CTC_ERROR_GOTO(ctc_hash_traverse(p_usw_acl_master[lchip]->udf_entry, _sys_usw_acl_wb_sync_udf_entry, (void*) (&wb_data)), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_UDF_ENTRY);
    }
#if 0
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_FIXED_KEY)
    {
        /*sync acl fixed key*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_fixed_key_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_FIXED_KEY);
        user_data.data0 = (void*)&wb_data;
        user_data.value0 = lchip;
        CTC_ERROR_RETURN(ctc_vector_traverse(p_usw_acl_master[lchip]->fixed_key_vec, _sys_usw_acl_wb_sync_fixed_key, (void*)&user_data));

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_RETURN(ctc_wb_add_entry(&wb_data));
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_FIXED_KEY);
    }
#endif

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_FLEX_KEY)
    {
        /*sync acl flex key*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_flex_key_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_FLEX_KEY);
        user_data.data0 = (void*)(&wb_data);
        user_data.value0 = lchip;
        CTC_ERROR_GOTO(ctc_vector_traverse(p_usw_acl_master[lchip]->fixed_key_vec, _sys_usw_acl_wb_sync_flex_key, (void*)&user_data),ret, done);

        user_data.value0 = lchip | (1 << 8);
        CTC_ERROR_GOTO(ctc_vector_traverse(p_usw_acl_master[lchip]->flex_key_vec, _sys_usw_acl_wb_sync_flex_key, (void*)&user_data),ret, done);

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data),ret, done);
        }

        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_FLEX_KEY);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_ACL_SUBID_ASET)
    {
        if(drv_vchip_get_pp_base(lchip) != lchip)
        {
            SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_ASET, 0);
            goto done;
        }
        /*sync acl flex key*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_acl_aset_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_ASET);
        CTC_ERROR_GOTO(ctc_vector_traverse(p_usw_acl_master[lchip]->aset_vec, _sys_usw_acl_wb_sync_aset, (void*)&wb_data),ret, done);

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data),ret, done);
        }

        CTC_WB_SYNC_END_DATA(CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_ASET);
    }

    done:
    SYS_USW_ACL_UNLOCK(lchip);
    CTC_WB_FREE_BUFFER(wb_data.buffer);
    return ret;
}

int32
sys_usw_acl_wb_restore(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    uint16 loop = 0;
    uint16 loop_j = 0;
    uint32 entry_cnt = 0;
    ctc_wb_query_t wb_query;
    sys_wb_acl_udf_entry_t wb_udf;
    sys_wb_acl_udf_entry_t* p_wb_udf = &wb_udf;
    sys_wb_acl_master_t* p_wb_acl_master = NULL;
    sys_wb_acl_group_t wb_acl_group;
    sys_wb_acl_group_t* p_wb_acl_group = &wb_acl_group;
    sys_wb_acl_tcam_entry_t wb_acl_entry;
    sys_wb_acl_hash_entry_t wb_hash_entry;
    sys_wb_acl_block_t wb_acl_block;
    sys_wb_acl_block_t* p_wb_block = &wb_acl_block;
    sys_wb_acl_lt_block_t wb_acl_lt_block;
    sys_wb_acl_lt_block_t* p_wb_lt_block = &wb_acl_lt_block;
    sys_wb_acl_flex_key_t wb_acl_fk;
    sys_wb_acl_flex_key_t* p_wb_acl_fk = &wb_acl_fk;
    sys_wb_acl_aset_t wb_aset;
    sys_acl_aset_t* p_aset = NULL;
    void* p_acl_fk = NULL;
    sys_acl_flex_key_t* p_fk = NULL;
    ctc_list_pointer_t node_list;
    ctc_list_pointer_node_t* node = NULL;
    sys_acl_group_t* p_acl_group = NULL;
    sys_acl_entry_t* p_acl_entry = NULL;
    sys_acl_udf_entry_t* p_udf = NULL;
    sys_acl_cid_action_t sys_cid_action;
    DsCategoryIdPairHashLeftKey_m cid_hash_key;
    uint32* p_data_entry = NULL;
    uint32* p_mask_entry = NULL;
    tbl_entry_t              cid_tcam_key;
    uint32 ad_index = 0;
    uint32 cmd = 0;
    uint32 tbl_key = 0;
    uint32 tbl_ad = 0;
    uint32 temp_index = 0;
    sys_usw_opf_t opf = {0};
    ParserUdfCamResult_m udf_rst[SYS_UDF_CAM_TYPE_NUM];
    uint8 level_status[16] = {0};
    uint8 expand_blocks = 0;
    uint8 compress_blocks = 0;
    uint8 acl_max_block_num = 0;
    uint16 udf_mapped_index[CTC_ACL_UDF_BYTE_NUM] = {0};
    ProgramAclRangeOpCtl_m* range_ctl = NULL;
    sys_acl_buffer_t* temp_buffer = NULL;
    sys_acl_udf_ad_t *p_udf_ad = NULL;
    uint8  mem_id = 0;
    uint8 dir = 0;

    sal_memset(&cid_tcam_key, 0, sizeof(cid_tcam_key));
    sal_memset(&cid_hash_key, 0, sizeof(cid_hash_key));
    sal_memset(&sys_cid_action, 0, sizeof(sys_cid_action));
    sal_memset(&wb_query, 0, sizeof(ctc_wb_query_t));
    sal_memset(&node_list, 0, sizeof(ctc_list_pointer_t));
    sal_memset(udf_rst, 0, SYS_UDF_CAM_TYPE_NUM * sizeof(ParserUdfCamResult_m));
    MALLOC_ZERO(MEM_ACL_MODULE, range_ctl, sizeof(ProgramAclRangeOpCtl_m)*3);
    p_data_entry = (uint32*)mem_malloc(MEM_ACL_MODULE, sizeof(uint32)*MAX_ENTRY_WORD);
    p_mask_entry = (uint32*)mem_malloc(MEM_ACL_MODULE, sizeof(uint32)*MAX_ENTRY_WORD);
    p_wb_acl_master = (sys_wb_acl_master_t*)mem_malloc(MEM_ACL_MODULE, sizeof(sys_wb_acl_master_t));
    temp_buffer = (sys_acl_buffer_t*)mem_malloc(MEM_ACL_MODULE, sizeof(sys_acl_buffer_t));
    if ( (NULL == p_data_entry) || (NULL == p_mask_entry) || (NULL == p_wb_acl_master) || (NULL == temp_buffer) || (NULL == range_ctl))
    {
        ret = CTC_E_NO_MEMORY;
        goto done;
    }
    sal_memset(p_data_entry, 0, sizeof(uint32)*MAX_ENTRY_WORD);
    sal_memset(p_mask_entry, 0, sizeof(uint32)*MAX_ENTRY_WORD);
    cid_tcam_key.data_entry = p_data_entry;
    cid_tcam_key.mask_entry = p_mask_entry;

    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);

    /*restore acl master*/
    /* set default value to new added fields, default value may not be zeros */
    sal_memset(p_wb_acl_master, 0, sizeof(sys_wb_acl_master_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_acl_master_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MASTER);
    CTC_ERROR_GOTO((ctc_wb_query_entry(&wb_query)), ret, done);
    if (1 != wb_query.valid_cnt || 1 != wb_query.is_end)
    {
        CTC_WB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "query acl master error! valid_cnt: %d, is_end: %d.\n", wb_query.valid_cnt, wb_query.is_end);
        ret = CTC_E_NONE;
        goto done;
    }

    sal_memcpy((uint8*)p_wb_acl_master, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);

    p_usw_acl_master[lchip]->upa_en = p_wb_acl_master->sort_mode;
    p_usw_acl_master[lchip]->league_update_bmp = p_wb_acl_master->league_update_bmp;
    p_usw_acl_master[lchip]->glb_presel_en = p_wb_acl_master->glb_presel_en;
    p_usw_acl_master[lchip]->srv6_rsv_udf_idx = p_wb_acl_master->srv6_rsv_udf_idx;
    p_usw_acl_master[lchip]->egs_league_update_bmp = p_wb_acl_master->egs_league_update_bmp;
    p_usw_acl_master[lchip]->global_pp_en_bmp[0] = p_wb_acl_master->global_pp_en_bmp[0];
    p_usw_acl_master[lchip]->global_pp_en_bmp[1] = p_wb_acl_master->global_pp_en_bmp[1];

    if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_ACL, p_wb_acl_master->version))
    {
        ret = CTC_E_VERSION_MISMATCH;
        goto done;
    }

    for(loop=0;loop<SYS_ACL_HASH_KEY_TYPE_NUM;loop++)
    {
        for(loop_j=0;loop_j<SYS_ACL_HASH_SEL_PROFILE_MAX;loop_j++)
        {
            sal_memcpy(&p_usw_acl_master[lchip]->hash_sel_key_union_filed[loop][loop_j], &p_wb_acl_master->hash_sel_key_union_filed[loop][loop_j],sizeof(sys_wb_hash_sel_field_union_t));
        }
    }

    if(DRV_FROM_TMM(lchip))
    {
    /*restore acl lt block, MUST restore before presel entry*/
    /* set default value to new added fields, default value may not be zeros */
    sal_memset(&wb_acl_lt_block, 0, sizeof(sys_wb_acl_lt_block_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_acl_lt_block_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_LT_BLOCK);
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)&wb_acl_lt_block, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;

        loop = p_wb_lt_block->block_id;
        p_usw_acl_master[lchip]->lt_block[loop].entry_valid = p_wb_lt_block->entry_valid;
        p_usw_acl_master[lchip]->lt_block[loop].is_key160 = p_wb_lt_block->is_key160;
        p_usw_acl_master[lchip]->lt_block[loop].ltid_bitmap = p_wb_lt_block->ltid_bitmap;
        /*p_usw_acl_master[lchip]->lt_block[loop].valid = p_wb_lt_block->valid;*/
        p_usw_acl_master[lchip]->lt_block[loop].fpab.start_offset[0] = p_wb_lt_block->start_offset;
        p_usw_acl_master[lchip]->lt_block[loop].fpab.entry_count = p_wb_lt_block->entry_count;
        p_usw_acl_master[lchip]->lt_block[loop].fpab.free_count = p_wb_lt_block->entry_count;
        p_usw_acl_master[lchip]->lt_block[loop].fpab.sub_entry_count[0] = p_wb_lt_block->entry_count;
        p_usw_acl_master[lchip]->lt_block[loop].fpab.sub_free_count[0] = p_wb_lt_block->entry_count;

        mem_free(p_usw_acl_master[lchip]->lt_block[loop].fpab.entries);
        if (p_usw_acl_master[lchip]->lt_block[loop].fpab.entry_count)
        {
            MALLOC_ZERO(MEM_ACL_MODULE, p_usw_acl_master[lchip]->lt_block[loop].fpab.entries,\
                p_usw_acl_master[lchip]->lt_block[loop].fpab.entry_count*sizeof(ctc_fpa_entry_t*));
            if(NULL == p_usw_acl_master[lchip]->lt_block[loop].fpab.entries)
            {
                ret = CTC_E_NO_MEMORY;
                goto done;
            }
        }
    CTC_WB_QUERY_ENTRY_END((&wb_query));
    }

    sal_memset(&wb_acl_block, 0, sizeof(sys_wb_acl_block_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_acl_block_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_BLOCK);
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)&wb_acl_block, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;

        loop = p_wb_block->block_id;
        p_usw_acl_master[lchip]->block[loop].entry_num = p_wb_block->entry_num;
        p_usw_acl_master[lchip]->block[loop].expand_blk_id = p_wb_block->expand_blk_id;
        p_usw_acl_master[lchip]->block[loop].block_status = p_wb_block->block_status;
        p_usw_acl_master[lchip]->block[loop].valid = p_wb_block->valid;
        if (0xFF != p_wb_block->prev_block)
        {
            p_usw_acl_master[lchip]->block[loop].prev = &p_usw_acl_master[lchip]->block[p_wb_block->prev_block];
        }
        if (0xFF != p_wb_block->next_block)
        {
            p_usw_acl_master[lchip]->block[loop].next = &p_usw_acl_master[lchip]->block[p_wb_block->next_block];
        }
        p_usw_acl_master[lchip]->block[loop].fpab.entry_count = p_wb_block->entry_count;
        p_usw_acl_master[lchip]->block[loop].fpab.free_count = p_wb_block->entry_count;
        p_usw_acl_master[lchip]->block[loop].fpab.same_size = p_wb_block->same_size;
        p_usw_acl_master[lchip]->block[loop].fpab.base = p_wb_block->fpa_block_base;
        p_usw_acl_master[lchip]->block[loop].fpab.part = p_wb_block->part;
        p_usw_acl_master[lchip]->block[loop].fpab.part_num = p_wb_block->part_num;
        if (p_wb_block->part_num > 1 && (p_wb_block->part_num - 1) != p_wb_block->part)
        {
            p_usw_acl_master[lchip]->block[loop].fpab.next = &p_usw_acl_master[lchip]->block[loop+1].fpab;
        }
        sal_memcpy(p_usw_acl_master[lchip]->block[loop].fpab.start_offset, p_wb_block->start_offset, sizeof(uint16)*CTC_FPA_KEY_SIZE_NUM);
        sal_memcpy(p_usw_acl_master[lchip]->block[loop].fpab.sub_entry_count, p_wb_block->sub_entry_count, sizeof(uint16)*CTC_FPA_KEY_SIZE_NUM);
        sal_memcpy(p_usw_acl_master[lchip]->block[loop].fpab.sub_free_count, p_wb_block->sub_entry_count, sizeof(uint16)*CTC_FPA_KEY_SIZE_NUM);

        sal_memcpy(p_usw_acl_master[lchip]->league[loop].lkup_level_start, p_wb_block->lkup_level_start, sizeof(uint16)*ACL_IGS_BLOCK_MAX_NUM);
        sal_memcpy(p_usw_acl_master[lchip]->league[loop].lkup_level_count, p_wb_block->lkup_level_count, sizeof(uint16)*ACL_IGS_BLOCK_MAX_NUM);
        p_usw_acl_master[lchip]->league[loop].lkup_level_bitmap = p_wb_block->lkup_level_bitmap;
        p_usw_acl_master[lchip]->league[loop].lkup_level_bitmap |= (p_wb_block->lkup_level_bitmap_high << 16);
        p_usw_acl_master[lchip]->league[loop].merged_to = p_wb_block->merged_to;
        p_usw_acl_master[lchip]->league[loop].hdr_block_id = p_wb_block->hdr_block;
        p_usw_acl_master[lchip]->league[loop].size = p_wb_block->size;

        /* set stats ram to global or pp */
        dir = loop < ACL_IGS_BLOCK_MAX_NUM ? CTC_INGRESS : CTC_EGRESS;
        if (MCHIP_F_STATS(lchip)->set_ram_pp_property && CTC_IS_BIT_SET(p_usw_acl_master[lchip]->global_pp_en_bmp[dir], (loop%ACL_IGS_BLOCK_MAX_NUM)))
        {
            MCHIP_F_STATS(lchip)->set_ram_pp_property(lchip, dir, (loop%ACL_IGS_BLOCK_MAX_NUM), p_wb_block->lkup_level_bitmap, 1);
        }

        mem_free(p_usw_acl_master[lchip]->block[loop].fpab.entries);
        if(p_usw_acl_master[lchip]->block[loop].fpab.entry_count)
        {
            MALLOC_ZERO(MEM_ACL_MODULE, p_usw_acl_master[lchip]->block[loop].fpab.entries,\
                p_usw_acl_master[lchip]->block[loop].fpab.entry_count*sizeof(ctc_fpa_entry_t*));
            if(NULL == p_usw_acl_master[lchip]->block[loop].fpab.entries)
            {
                ret = CTC_E_NO_MEMORY;
                goto done;
            }
        }
        if (p_wb_block->vblock_entry_count)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO,"wb restore - block id: %u, vblock entry count :%u \n", loop, p_wb_block->vblock_entry_count);
            MALLOC_ZERO(MEM_ACL_MODULE, p_usw_acl_master[lchip]->block[loop].fpab.vblock, sizeof(ctc_fpa_block_t));
            if(NULL == p_usw_acl_master[lchip]->block[loop].fpab.vblock)
            {
                ret = CTC_E_NO_MEMORY;
                goto done;
            }
            MALLOC_ZERO(MEM_ACL_MODULE, p_usw_acl_master[lchip]->block[loop].fpab.vblock->entries,\
                p_wb_block->vblock_entry_count*sizeof(ctc_fpa_entry_t*));
            if(NULL == p_usw_acl_master[lchip]->block[loop].fpab.vblock->entries)
            {
                ret = CTC_E_NO_MEMORY;
                goto done;
            }
            p_usw_acl_master[lchip]->block[loop].fpab.vblock->same_size = 1;
            p_usw_acl_master[lchip]->block[loop].fpab.vblock->part_num = 1;
            p_usw_acl_master[lchip]->block[loop].fpab.vblock->entry_count = p_wb_block->vblock_entry_count;
            p_usw_acl_master[lchip]->block[loop].fpab.vblock->free_count = p_wb_block->vblock_entry_count;
            p_usw_acl_master[lchip]->block[loop].fpab.vblock->sub_entry_count[CTC_FPA_KEY_SIZE_160] = p_wb_block->vblock_sub_entry_count;
            p_usw_acl_master[lchip]->block[loop].fpab.vblock->sub_free_count[CTC_FPA_KEY_SIZE_160] = p_wb_block->vblock_sub_entry_count;
        }
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*restore acl flex key*/
    sal_memset(&wb_acl_fk, 0, sizeof(sys_wb_acl_flex_key_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_acl_flex_key_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_FLEX_KEY);
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)&wb_acl_fk, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        if(wb_acl_fk.is_flex_key)
        {
            uint8  block_num = 0;

            if(wb_acl_fk.node_type == SYS_ACL_FLEX_KEY_NODE_HASH)
            {
                block_num = ACL_HASH_MAX_NUM;
                SYS_ACL_INIT_FK(block_num, sys_acl_flex_hash_t, p_acl_fk);
            }
            else
            {
                block_num = (wb_acl_fk.dir == CTC_EGRESS)? ACL_EGS_BLOCK_MAX_NUM :ACL_IGS_BLOCK_MAX_NUM;
                SYS_ACL_INIT_FK(block_num, sys_acl_flex_key_t, p_acl_fk);
            }
        }
        else
        {
             MALLOC_ZERO(MEM_ACL_MODULE, p_acl_fk, sizeof(sys_acl_fixed_key_t));
        }
        if (NULL == p_acl_fk)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        entry_cnt++;

        CTC_ERROR_RETURN(_sys_usw_acl_wb_mapping_flex_key(p_wb_acl_fk, p_acl_fk, 0, lchip));
        if(wb_acl_fk.is_flex_key)
        {
            ctc_vector_add( p_usw_acl_master[lchip]->flex_key_vec, SYS_ACL_FLEX_KEY_IDX(wb_acl_fk.dir, wb_acl_fk.key_type), (void*)p_acl_fk);
        }
        else
        {
            ctc_vector_add( p_usw_acl_master[lchip]->fixed_key_vec, wb_acl_fk.key_type, (void*)p_acl_fk);
        }
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    if (MCHIP_ACL(lchip)->wb_restore)
    {
        CTC_ERROR_GOTO(MCHIP_ACL(lchip)->wb_restore(lchip, &wb_query), ret, done);
    }

    /* restore aset */
    sal_memset(&wb_aset, 0, sizeof(sys_wb_acl_aset_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_acl_aset_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_ASET);
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)&wb_aset, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);

        MALLOC_ZERO(MEM_ACL_MODULE, p_aset, sizeof(sys_acl_aset_t));
        if (NULL == p_aset)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        entry_cnt++;

        _sys_usw_acl_wb_mapping_aset(lchip, &wb_aset, p_aset, 0);
        ctc_vector_add( p_usw_acl_master[lchip]->aset_vec, p_aset->aset_id, (void*)p_aset);
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*process for acl expand tcam*/
    CTC_ERROR_GOTO(_sys_usw_acl_get_ext_tcam_status(lchip, (uint8*)level_status), ret, done);
    acl_max_block_num = DRV_FROM_AT(lchip) ? ACL_IGS_BLOCK_MAX_NUM + ACL_EGS_BLOCK_MAX_NUM : ACL_IGS_BLOCK_MAX_NUM;
    for(loop=0; loop < acl_max_block_num; loop++)
    {
        mem_id = SYS_USW_ACL_TCAM_BASE + loop;
        if(level_status[loop]==0 && p_usw_acl_master[lchip]->block[loop].entry_num > SYS_USW_PRIVATE_TCAM_SIZE)
        {
            CTC_BIT_SET(expand_blocks, loop);
        }
        else if(level_status[loop]==1 && p_usw_acl_master[lchip]->block[loop].entry_num == SYS_USW_PRIVATE_TCAM_SIZE)\
        {
            CTC_BIT_SET(compress_blocks, loop);
        }
    }
    if(expand_blocks != 0 || compress_blocks != 0)
    {
        CTC_ERROR_GOTO(sys_usw_ftm_adjust_flow_tcam(lchip, expand_blocks, compress_blocks), ret, done);
    }

    /* restore udf and opf */
    /* set default value to new added fields, default value may not be zeros */
    sal_memset(&wb_udf, 0, sizeof(sys_wb_acl_udf_entry_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_acl_udf_entry_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_UDF_ENTRY);
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        p_udf = mem_malloc(MEM_ACL_MODULE, sizeof(sys_acl_udf_entry_t));
        if (NULL == p_udf)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(p_udf, 0, sizeof(sys_acl_udf_entry_t));

        sal_memcpy((uint8*)&wb_udf, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;

        CTC_ERROR_GOTO(_sys_usw_acl_wb_mapping_udf(p_wb_udf, p_udf, 0), ret, done);
        if (DRV_FROM_TMM(lchip) && !p_udf->is_sudf && !p_udf->is_installed)
        {
            CTC_ERROR_GOTO(_sys_usw_acl_udf_rebuild_buffer_from_hw(lchip, p_udf), ret, done);
        }
        ctc_hash_insert(p_usw_acl_master[lchip]->udf_entry, (void*) p_udf);
        p_udf_ad = ctc_vector_get(p_usw_acl_master[lchip]->udf_ad, p_udf->udf_hit_index);
        if(p_udf_ad)
        {
            p_udf_ad->ref_cnt++;
        }
        else
        {
            p_udf_ad = mem_malloc(MEM_ACL_MODULE, sizeof(sys_acl_udf_ad_t));
            if (NULL == p_udf_ad)
            {
                ret = CTC_E_NO_MEMORY;
                goto done;
            }
            p_udf_ad->ref_cnt = 1;
            ctc_vector_add(p_usw_acl_master[lchip]->udf_ad, p_udf->udf_hit_index, p_udf_ad);
        }

        if(p_udf->key_index_used && !p_udf->is_sudf)
        {
            sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
            opf.pool_index = SYS_USW_ACL_UDF_MAPPED_INDEX;
            opf.pool_type = p_usw_acl_master[lchip]->opf_type_udf;
            ret = sys_usw_opf_alloc_offset_from_position(lchip, &opf, 1, p_udf->udf_hit_index);
        }
        if(p_usw_acl_master[lchip]->udf_fpa_en && !p_udf->is_sudf)
        {
            p_usw_acl_master[lchip]->udf_block.fpab.entries[p_udf->key_index] = &p_udf->fpae;
            p_udf->fpae.offset_a = p_udf->key_index;
            p_usw_acl_master[lchip]->udf_block.fpab.sub_free_count[CTC_FPA_KEY_SIZE_80]--;
        }
        sys_usw_com_wb_restore_entry_hash(lchip, p_udf->udf_id, MEM_ACL_MODULE,
                        p_usw_acl_master[SYS_PP_BASE(lchip)]->entry_hash_db[SYS_COM_ENTRY_HASH_ACL_UDF_ENTRY]);
    CTC_WB_QUERY_ENTRY_END((&wb_query));
    ret = (ret == CTC_E_EXIST) ? CTC_E_NONE : ret;
    if (ret != CTC_E_NONE)
    {
        goto done;
    }

    if(DRV_FROM_TMM(lchip))
    {
        sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
        opf.pool_type = p_usw_acl_master[lchip]->opf_type_udf;
        opf.pool_index = SYS_USW_ACL_UDF_MAPPED_INDEX1;
        for(loop=512; loop<1024; loop++)
        {
            CTC_ERROR_GOTO(sys_usw_parser_io_get_parser_udf_cam_result(lchip, &udf_rst[SYS_UDF_CAM_TYPE_FIB], loop, 1, p_usw_acl_master[lchip]->udf_mode), ret, done);
            udf_mapped_index[SYS_UDF_CAM_TYPE_ACL] = GetParserUdfCamResult(V, udfMappedIndex_f, &udf_rst[SYS_UDF_CAM_TYPE_ACL]);
            if (udf_mapped_index[SYS_UDF_CAM_TYPE_ACL])
            {
                ret = sys_usw_opf_alloc_offset_from_position(lchip, &opf, 1, udf_mapped_index[SYS_UDF_CAM_TYPE_ACL]);
            }
        }
        ret = (ret == CTC_E_EXIST) ? CTC_E_NONE : ret;
        if (ret != CTC_E_NONE)
        {
            goto done;
        }

        opf.pool_index = SYS_USW_ACL_SUDF_AD_INDEX;
        for(loop=512; loop<1024; loop++)
        {
            CTC_ERROR_GOTO(sys_usw_parser_io_get_parser_udf_cam_result(lchip, &udf_rst[SYS_UDF_CAM_TYPE_FIB], loop, 1, p_usw_acl_master[lchip]->udf_mode), ret, done);
            if (GetParserUdfCamResult(V, udfMappedIndex_f, &udf_rst[SYS_UDF_CAM_TYPE_ACL]))
            {
                ret = sys_usw_opf_alloc_offset_from_position(lchip, &opf, 1, loop);
            }
        }
        if (ret != CTC_E_NONE)
        {
            goto done;
        }
    }
    /*restore acl group*/
    /* set default value to new added fields, default value may not be zeros */
    sal_memset(&wb_acl_group, 0, sizeof(sys_wb_acl_group_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_acl_group_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_GROUP);
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        p_acl_group = mem_malloc(MEM_ACL_MODULE, sizeof(sys_acl_group_t));
        if (NULL == p_acl_group)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(p_acl_group, 0, sizeof(sys_acl_group_t));
        p_acl_group->lchip = lchip;

        sal_memcpy((uint8*)&wb_acl_group, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;

        CTC_ERROR_GOTO(_sys_usw_acl_wb_mapping_group(p_wb_acl_group, p_acl_group, 0), ret, done);
        if((!SYS_ACL_IS_RSV_GROUP(p_acl_group->group_id)))
        {
            uint16 block_id = (CTC_INGRESS == p_acl_group->group_info.dir ? p_acl_group->group_info.block_id: p_acl_group->group_info.block_id + ACL_IGS_BLOCK_MAX_NUM);
            ctc_slist_add_tail(SYS_ACL_BLOCK(lchip, block_id).group_list, &p_acl_group->head);
        }
        ctc_hash_insert(p_usw_acl_master[lchip]->group, (void*) p_acl_group);

        if (p_acl_group->group_id == SYS_ACL_GROUP_ID_WLAN_CRYPT_ERROR)
        {
            p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu = 1;
        }
        if (p_acl_group->group_id == SYS_ACL_GROUP_ID_DOT1AE_CRYPT_ERROR)
        {
            p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu = 1;
        }
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*restore acl entry*/
    /* set default value to new added fields, default value may not be zeros */
    cmd = DRV_IOR(ParserRangeOpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &range_ctl[0]));
    cmd = DRV_IOR(ProgramAclRangeOpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &range_ctl[1]));
    cmd = DRV_IOR(EgrProgramAclRangeOpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &range_ctl[2]));

    sal_memset(&wb_acl_entry, 0, sizeof(sys_wb_acl_tcam_entry_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_acl_tcam_entry_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY);
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        p_acl_entry = mem_malloc(MEM_ACL_MODULE, sizeof(sys_acl_entry_t));
        if (NULL == p_acl_entry)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(p_acl_entry, 0, sizeof(sys_acl_entry_t));
        sal_memset(temp_buffer, 0, sizeof(sys_acl_buffer_t));
        p_acl_entry->ua = (void*)temp_buffer;
        sal_memcpy((uint8*)&wb_acl_entry, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;

        /* restore lchip before mapping entry*/
        CTC_ERROR_GOTO(_sys_usw_acl_wb_mapping_entry(lchip, &wb_acl_entry, p_acl_entry, 0, (void*)range_ctl, &node_list), ret, done);
        if(p_acl_entry->fpae.flag == FPA_ENTRY_FLAG_UNINSTALLED)
        {
            continue;
        }
        ctc_hash_insert(p_usw_acl_master[lchip]->entry, (void*) p_acl_entry);
        sys_usw_com_wb_restore_entry_hash(lchip, wb_acl_entry.entry_id, MEM_ACL_MODULE,
                        p_usw_acl_master[SYS_PP_BASE(lchip)]->entry_hash_db[SYS_COM_ENTRY_HASH_ACL_ENTRY]);
    CTC_WB_QUERY_ENTRY_END((&wb_query));

     /*need update link block after entry restore*/
    for (node = ctc_list_pointer_head(&node_list); node; node = ctc_list_pointer_next(node))
    {
        p_acl_entry = _ctc_container_of(node, sys_acl_entry_t, head);

        if(MCHIP_ACL(lchip)->compress_link_block)
        {
            uint16 block_id = (CTC_INGRESS == p_acl_entry->group->group_info.dir ? p_acl_entry->group->group_info.block_id: p_acl_entry->group->group_info.block_id + ACL_IGS_BLOCK_MAX_NUM);
            p_fk = SYS_ACL_GET_FK(lchip ,p_acl_entry);
            MCHIP_ACL(lchip)->compress_link_block(lchip, &(p_usw_acl_master[lchip]->block[block_id]), p_fk);
        }
        mem_free(p_acl_entry);
        /*_sys_usw_acl_free_entry_node_data((void*)p_acl_entry, &free_entry);*/
    }

    sal_memset(&wb_hash_entry, 0, sizeof(sys_wb_acl_hash_entry_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_acl_hash_entry_t, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_HASH_ENTRY);
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query))
        sys_acl_hash_entry_t* p_acl_hash = NULL;
        p_acl_hash = mem_malloc(MEM_ACL_MODULE, sizeof(sys_acl_hash_entry_t));
        if (NULL == p_acl_hash)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(p_acl_hash, 0, sizeof(sys_acl_hash_entry_t));
        sal_memset(temp_buffer, 0, sizeof(sys_acl_buffer_t));
        p_acl_hash->ua = (void*)temp_buffer;
        sal_memcpy((uint8*)&wb_hash_entry, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;

        /* restore lchip before mapping entry*/
        CTC_ERROR_GOTO(_sys_usw_acl_wb_mapping_hash_entry(lchip, &wb_hash_entry, p_acl_hash, 0), ret, done);
        if(p_acl_hash->installed == FPA_ENTRY_FLAG_UNINSTALLED)
        {
            mem_free(p_acl_hash);
            continue;
        }
        ctc_hash_insert(p_usw_acl_master[lchip]->entry, (void*) p_acl_hash);
        sys_usw_com_wb_restore_entry_hash(lchip, wb_hash_entry.entry_id, MEM_ACL_MODULE,
                        p_usw_acl_master[SYS_PP_BASE(lchip)]->entry_hash_db[SYS_COM_ENTRY_HASH_ACL_ENTRY]);
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*restore cid tcam */
    /*MUST restore ofb first*/
    CTC_ERROR_GOTO(sys_usw_ofb_wb_restore(lchip, p_usw_acl_master[lchip]->ofb_type_cid,
                                                CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_CID), ret, done);
    tbl_key = DsCategoryIdPairTcamKey_t;
    for(loop=0; loop<MCHIP_CAP(SYS_CAP_ACL_TCAM_CID_PAIR) - 1; loop++)
    {
        cmd = DRV_IOR(tbl_key, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, loop, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &cid_tcam_key));
        if(GetDsCategoryIdPairTcamKey(V, destCategoryIdClassfied_f, p_data_entry)
          && GetDsCategoryIdPairTcamKey(V, srcCategoryIdClassfied_f, p_data_entry))
        {
            CTC_ERROR_GOTO(sys_usw_ofb_alloc_offset_from_position(lchip, p_usw_acl_master[lchip]->ofb_type_cid,
                                                                                            0, loop, NULL),ret, done);
        }
        else if(GetDsCategoryIdPairTcamKey(V, destCategoryIdClassfied_f, p_data_entry)
          || GetDsCategoryIdPairTcamKey(V, srcCategoryIdClassfied_f, p_data_entry))
        {
            CTC_ERROR_GOTO(sys_usw_ofb_alloc_offset_from_position(lchip, p_usw_acl_master[lchip]->ofb_type_cid,
                                                                                            1, loop, NULL),ret, done);
        }
    }

    /*restore cid hash action spool*/
    for(loop=0; loop < 512; loop++)
    {
        if(loop < 256)
        {
            tbl_key = DsCategoryIdPairHashLeftKey_t;
            tbl_ad = DsCategoryIdPairHashLeftAd_t;
            temp_index = loop;
        }
        else
        {
            tbl_key = DsCategoryIdPairHashRightKey_t;
            tbl_ad = DsCategoryIdPairHashRightAd_t;
            temp_index  = loop-256;
        }

        cmd = DRV_IOR(tbl_key, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, temp_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &cid_hash_key));

        if(GetDsCategoryIdPairHashLeftKey(V, array_0_valid_f, &cid_hash_key))
        {
            ad_index = GetDsCategoryIdPairHashLeftKey(V, array_0_adIndex_f, &cid_hash_key);
            sys_cid_action.is_left = (loop < 256) ? 1 : 0;
            sys_cid_action.ad_index = ad_index;

            cmd = DRV_IOR(tbl_ad, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, ad_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &sys_cid_action.ds_cid_action));

            CTC_ERROR_RETURN(ctc_spool_add(p_usw_acl_master[lchip]->cid_spool, &sys_cid_action, NULL, NULL));
        }

        if(GetDsCategoryIdPairHashLeftKey(V, array_1_valid_f, &cid_hash_key))
        {
            ad_index = GetDsCategoryIdPairHashLeftKey(V, array_1_adIndex_f, &cid_hash_key);
            sys_cid_action.is_left = (loop < 256) ? 1 : 0;
            sys_cid_action.ad_index = ad_index;

            cmd = DRV_IOR(tbl_ad, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, ad_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &sys_cid_action.ds_cid_action));
            CTC_ERROR_RETURN(ctc_spool_add(p_usw_acl_master[lchip]->cid_spool, &sys_cid_action, NULL, NULL));
        }

    }


done:
    CTC_WB_FREE_BUFFER(wb_query.buffer);

    if (p_data_entry)
    {
        mem_free(p_data_entry);
    }

    if (p_mask_entry)
    {
        mem_free(p_mask_entry);
    }

    if (p_wb_acl_master)
    {
        mem_free(p_wb_acl_master);
    }
    if (range_ctl)
    {
        mem_free(range_ctl);
    }
    if (temp_buffer)
    {
        mem_free(temp_buffer);
    }
    CTC_ERROR_RETURN(sys_usw_scl_wb_restore_range_info(lchip));

    return ret;
}

STATIC int32
_sys_usw_acl_dump_vlan_edit_spool_db(void *node, void* user_date)
{
    sys_traverse_t* p_traverse = (sys_traverse_t*)user_date;
    uint32* p_cnt = (uint32*)p_traverse->data1;
    sal_file_t p_f = (sal_file_t)p_traverse->data;
    ctc_spool_node_t* p_node = (ctc_spool_node_t*)node;
    sys_acl_vlan_edit_t* p_vlan_edit = (sys_acl_vlan_edit_t*)p_node->data;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = p_traverse->value1;
#endif
    if(0xFFFFFFFF == p_node->ref_cnt)
    {
        SYS_DUMP_DB_LOG(p_f, "%-8u%-8u%-8u%-8u%-8u%-8u%-8u%-8u%-8u%-8u%-12u%-12u%-12s\n", *p_cnt, \
            p_vlan_edit->stag_op, p_vlan_edit->svid_sl, p_vlan_edit->scos_sl, p_vlan_edit->scfi_sl, \
            p_vlan_edit->ctag_op, p_vlan_edit->cvid_sl, p_vlan_edit->ccos_sl, p_vlan_edit->ccfi_sl, \
            p_vlan_edit->tpid_en, p_vlan_edit->tpid_index, p_vlan_edit->profile_id, "Static");
    }
    else
    {
        SYS_DUMP_DB_LOG(p_f, "%-8u%-8u%-8u%-8u%-8u%-8u%-8u%-8u%-8u%-8u%-12u%-12u%-12u\n", *p_cnt, \
            p_vlan_edit->stag_op, p_vlan_edit->svid_sl, p_vlan_edit->scos_sl, p_vlan_edit->scfi_sl, \
            p_vlan_edit->ctag_op, p_vlan_edit->cvid_sl, p_vlan_edit->ccos_sl, p_vlan_edit->ccfi_sl, \
            p_vlan_edit->tpid_en, p_vlan_edit->tpid_index, p_vlan_edit->profile_id, p_node->ref_cnt);
    }
    (*p_cnt)++;
    return CTC_E_NONE;
}
STATIC int32
_sys_usw_acl_dump_cid_ad_spool_db(void *node, void* user_date)
{
    sys_traverse_t* p_traverse = (sys_traverse_t*)user_date;
    uint32* p_cnt = (uint32*)p_traverse->data1;
    sal_file_t p_f = (sal_file_t)p_traverse->data;
    ctc_spool_node_t* p_node = (ctc_spool_node_t*)node;
    sys_acl_cid_action_t* p_cid_ad = (sys_acl_cid_action_t*)p_node->data;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = p_traverse->value1;
#endif
    if(0xFFFFFFFF == p_node->ref_cnt)
    {
        SYS_DUMP_DB_LOG(p_f, "%-12u%-20u%-20uStatic\n", (*p_cnt),p_cid_ad->ad_index, p_cid_ad->is_left);
    }
    else
    {
        SYS_DUMP_DB_LOG(p_f, "%-12u%-20u%-20u%-20u\n", (*p_cnt),p_cid_ad->ad_index, p_cid_ad->is_left, p_node->ref_cnt);
    }
    (*p_cnt)++;
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_acl_dump_hash_ad_spool_db(void *node, void* user_date)
{
    sys_traverse_t* p_traverse = (sys_traverse_t*)user_date;
    uint32* p_cnt = (uint32*)p_traverse->data1;
    sal_file_t p_f = (sal_file_t)p_traverse->data;
    ctc_spool_node_t* p_node = (ctc_spool_node_t*)node;
    sys_acl_hash_action_t* pa_node = (sys_acl_hash_action_t*)p_node->data;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = p_traverse->value1;
#endif
    if(0xFFFFFFFF == p_node->ref_cnt)
    {
        SYS_DUMP_DB_LOG(p_f, "%-12u%-24uStatic\n", (*p_cnt),pa_node->ad_index);
    }
    else
    {
        SYS_DUMP_DB_LOG(p_f, "%-12u%-24u%-20u\n", (*p_cnt), pa_node->ad_index, p_node->ref_cnt);
    }
    (*p_cnt)++;
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_acl_dump_cethertype_spool_db(void *node, void* user_date)
{
    sys_traverse_t* p_traverse = (sys_traverse_t*)user_date;
    uint32* p_cnt = (uint32*)p_traverse->data1;
    sal_file_t p_f = (sal_file_t)p_traverse->data;
    ctc_spool_node_t* p_node = (ctc_spool_node_t*)node;
    sys_register_cethertype_t* p_cethertype = (sys_register_cethertype_t*)p_node->data;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = p_traverse->value1;
#endif
    if(0xFFFFFFFF == p_node->ref_cnt)
    {
        SYS_DUMP_DB_LOG(p_f, "%-12u%-24uStatic\n", (*p_cnt), p_cethertype->index.index);
    }
    else
    {
        SYS_DUMP_DB_LOG(p_f, "%-12u%-24u%-20u\n", (*p_cnt), p_cethertype->index.index,  p_node->ref_cnt);
    }
    (*p_cnt)++;
    return CTC_E_NONE;
}

int32
_sys_usw_acl_dump_flex_key_db(void * arrary_date, void* user_date)
{
    uint8 block_id = 0;
    sys_acl_flex_key_t *fk = (sys_acl_flex_key_t *)arrary_date;
    sys_traverse_t* p_traverse = (sys_traverse_t*)user_date;
    uint32* p_cnt = (uint32*)p_traverse->data1;
    sal_file_t p_f = (sal_file_t)p_traverse->data;
    uint8 lchip = (uint32)p_traverse->value1;
    uint8 max_block_num = (SYS_ACL_FLEX_KEY_NODE_I_TCAM == fk->node_type)? (ACL_IGS_BLOCK_MAX_NUM): (ACL_EGS_BLOCK_MAX_NUM);

    if(SYS_ACL_FLEX_KEY_NODE_HASH == fk->node_type)
    {
        sys_acl_flex_hash_t *fk_hash = (sys_acl_flex_hash_t *)arrary_date;

        SYS_DUMP_DB_LOG(p_f, "%-12u%-12u%-12u%-12u\n", (*p_cnt), fk_hash->key_type, fk_hash->key_size, fk_hash->presel_cnt);
        SYS_DUMP_DB_LOG(p_f, "%-12s"," ");
    }
    else
    {
        SYS_DUMP_DB_LOG(p_f, "%-12u%-12u%-12u", (*p_cnt), fk->key_type, fk->key_size);
        SYS_DUMP_DB_LOG(p_f, p_usw_acl_master[lchip]->glb_presel_en ? "%-12u\n" : "0x%-10X\n", fk->presel_cnt);
        SYS_DUMP_DB_LOG(p_f, "%-12s"," ");
        SYS_ACL_IGS_BLK_LOOP(block_id, max_block_num)
        {
            if(CTC_IS_BIT_SET(fk->ltid_valid, block_id))
            {
                SYS_DUMP_DB_LOG(p_f, "%d:%d %d, ", block_id, fk->ltid[block_id], fk->entry_count[block_id]);
            }
        }
    }
    SYS_DUMP_DB_LOG(p_f, "\n");
    (*p_cnt)++;
    return CTC_E_NONE;
}

int32
_sys_usw_acl_dump_aset_db(void * arrary_date, void* user_date)
{
    sys_acl_aset_t *aset = (sys_acl_aset_t *)arrary_date;
    sys_traverse_t* p_traverse = (sys_traverse_t*)user_date;
    sal_file_t p_f = (sal_file_t)p_traverse->data;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = p_traverse->value1;
#endif
    SYS_DUMP_DB_LOG(p_f, "%-12u%-12u%-12u%-12u\n", aset->aset_id, aset->type, aset->is_static, aset->ref_cnt);
    return CTC_E_NONE;
}


int32
sys_usw_acl_dump_db(uint8 lchip, sal_file_t p_f,ctc_global_dump_db_t* p_dump_param)
{
    uint32 loop = 0;
    uint32 loop1 = 0;
    char*   hash_type_str[SYS_ACL_HASH_KEY_TYPE_NUM] = {"Mac", "Ipv4", "L2l3", "Mpls","Ipv6", "NSH"};
    sys_acl_block_t* pb = NULL;
    sys_hash_sel_field_union_t* p_sel_un = NULL;
    sys_acl_league_t* p_league = NULL;
    sys_traverse_t  param;
    uint32  spool_cnt = 1;

    SYS_ACL_INIT_CHECK();
    SYS_USW_ACL_LOCK(lchip);

    SYS_DUMP_DB_LOG(p_f, "%s\n", "# ACL");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "{");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "Master config:");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "--------------------------------------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-12s:%-12s%-12u%-12s%-12u%-12s%-12u%-12s%-12u\n","Key Count", \
        "80 bits",p_usw_acl_master[lchip]->key_count[0], "160 bits",p_usw_acl_master[lchip]->key_count[1],\
        "320 bits",p_usw_acl_master[lchip]->key_count[2], "640 bits",p_usw_acl_master[lchip]->key_count[3]);

    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Opf type of vlan edit", p_usw_acl_master[lchip]->opf_type_vlan_edit);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Opf type of hash ad", p_usw_acl_master[lchip]->opf_type_ad);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Opf type of hash cid ad", p_usw_acl_master[lchip]->opf_type_cid_ad);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Opf type of udf", p_usw_acl_master[lchip]->opf_type_udf);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Opf type of aset", p_usw_acl_master[lchip]->opf_type_aset);

    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Wlan crypt error to cpu", p_usw_acl_master[lchip]->wlan_crypt_error_to_cpu);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Dot1ae crypt error to cpu", p_usw_acl_master[lchip]->dot1ae_crypt_error_to_cpu);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","UPA enable", p_usw_acl_master[lchip]->upa_en);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","League update bmp", p_usw_acl_master[lchip]->league_update_bmp);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Egress League update bmp", p_usw_acl_master[lchip]->egs_league_update_bmp);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Global presel en", p_usw_acl_master[lchip]->glb_presel_en);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","UDF fpa enable", p_usw_acl_master[lchip]->udf_fpa_en);
    SYS_DUMP_DB_LOG(p_f, "%-36s: 0x%08x\n","ingress global pp en lkup bmp", p_usw_acl_master[lchip]->global_pp_en_bmp[0]);
    SYS_DUMP_DB_LOG(p_f, "%-36s: 0x%08x\n","egress  global pp en lkup bmp", p_usw_acl_master[lchip]->global_pp_en_bmp[1]);

    SYS_DUMP_DB_LOG(p_f, "\n%-36s\n","Block information:");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "-------------------------------------------------------------------------------------------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-16s%-16s%-16s%-16s%-16s%-16s%-16s%-6s%-16s\n","Block ID","Entry numer","Entry count","Free count",
                    "Expand block", "Block status", "Valid", "Prev block", "Next block");
    SYS_DUMP_DB_LOG(p_f, "%-16s%-16s%-16s%-16s%-16s\n","","Key size","Start offset", "Sub cnt","Sub free cnt");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "-------------------------------------------------------------------------------------------------------------------------------------------------");

    for(loop=0; loop < ACL_IGS_BLOCK_MAX_NUM + ACL_EGS_BLOCK_MAX_NUM; loop++)
    {
        pb = &p_usw_acl_master[lchip]->block[loop];
        SYS_DUMP_DB_LOG(p_f, "\n%-16u%-16u%-16u%-16u%-16u%-16u%-16u%-6u%-16u\n", loop, pb->entry_num, pb->fpab.entry_count, pb->fpab.free_count,
                        pb->expand_blk_id, pb->block_status, pb->valid, pb->prev? pb->prev->block_id: 0xFF, pb->next? pb->next->block_id: 0xFF);

        if(pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_80])
        {
            SYS_DUMP_DB_LOG(p_f, "%-16s%-16s%-16u%-16u%-16u%-16u\n", "","80 bits",pb->fpab.start_offset[CTC_FPA_KEY_SIZE_80],\
                pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_80],pb->fpab.sub_free_count[CTC_FPA_KEY_SIZE_80],pb->fpab.sub_rsv_count[CTC_FPA_KEY_SIZE_80]);
        }
        else
        {
            SYS_DUMP_DB_LOG(p_f, "%-16s%-16s%-16u%-16u%-16u%-16u\n", "","160 bits",pb->fpab.start_offset[CTC_FPA_KEY_SIZE_160],\
                pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_160],pb->fpab.sub_free_count[CTC_FPA_KEY_SIZE_160],pb->fpab.sub_rsv_count[CTC_FPA_KEY_SIZE_160]);
            SYS_DUMP_DB_LOG(p_f, "%-16s%-16s%-16u%-16u%-16u%-16u\n", "","320 bits",pb->fpab.start_offset[CTC_FPA_KEY_SIZE_320],\
                pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_320],pb->fpab.sub_free_count[CTC_FPA_KEY_SIZE_320],pb->fpab.sub_rsv_count[CTC_FPA_KEY_SIZE_320]);
            SYS_DUMP_DB_LOG(p_f, "%-16s%-16s%-16u%-16u%-16u%-16u\n", "","640 bits",pb->fpab.start_offset[CTC_FPA_KEY_SIZE_640],\
                pb->fpab.sub_entry_count[CTC_FPA_KEY_SIZE_640],pb->fpab.sub_free_count[CTC_FPA_KEY_SIZE_640],pb->fpab.sub_rsv_count[CTC_FPA_KEY_SIZE_640]);
        }

    }
    SYS_DUMP_DB_LOG(p_f, "%-16s%-16s%-16s%-16s\n","Block ID","Entry numer","Entry count","Free count");
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-36s\n","League information:");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "---------------------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-16s%-22s%-16s%-16s\n","Block ID","Lkup level bmp", "Merged to block id", "Header block");
    SYS_DUMP_DB_LOG(p_f, "%-16s%-22s%-16s%-16s\n","","Level", "Start", "Count");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "---------------------------------------------------------------------------");
    for(loop=0; loop < ACL_IGS_BLOCK_MAX_NUM + ACL_EGS_BLOCK_MAX_NUM; loop++)
    {
        p_league = &p_usw_acl_master[lchip]->league[loop];
        SYS_DUMP_DB_LOG(p_f, "\n%-16u0x%-20x%-16u%-16u\n", p_league->block_id, p_league->lkup_level_bitmap, p_league->merged_to, p_league->hdr_block_id);
        for(loop1=0; loop1 < ACL_IGS_BLOCK_MAX_NUM; loop1++)
        {
            SYS_DUMP_DB_LOG(p_f, "%-16s%-22u%-16u%-16u\n","",loop1, p_league->lkup_level_start[loop1], p_league->lkup_level_count[loop1]);
        }
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-36s\n","Hash select information:");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-16s%-12s%-14s%-14s%-16s%-16s%-16s%-16s%-16s\n","Key Type","Hash sel id", "Profile count","L4 field type","L4 field bmp", "port type", "l2l3 u13 type", "l3 u1 type","v6 ip mode" );
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------------------------------------");
    for(loop=0; loop < SYS_ACL_HASH_KEY_TYPE_NUM; loop++)
    {
        for(loop1=0; loop1 < SYS_ACL_HASH_SEL_PROFILE_MAX; loop1++)
        {
            p_sel_un = &(p_usw_acl_master[lchip]->hash_sel_key_union_filed[loop][loop1]);
            SYS_DUMP_DB_LOG(p_f, "%-16s%-12u%-14u%-14u%-16u%-16u%-16u%-16u%-16u\n", hash_type_str[loop], loop1,\
                p_usw_acl_master[lchip]->hash_sel_profile_count[loop][loop1],\
                p_sel_un->l4_port_field, p_sel_un->l4_port_field_bmp, p_sel_un->key_port_type, \
                                    p_sel_un->l2_l3_key_ul3_type, p_sel_un->l3_key_u1_type, p_sel_un->ipv6_key_ip_mode);
        }
    }

    SYS_DUMP_DB_LOG(p_f, "\n");

    sys_usw_opf_fprint_alloc_used_info(lchip, p_usw_acl_master[lchip]->opf_type_vlan_edit, p_f);
    SYS_DUMP_DB_LOG(p_f, "\n");
    sys_usw_opf_fprint_alloc_used_info(lchip, p_usw_acl_master[lchip]->opf_type_ad, p_f);
    SYS_DUMP_DB_LOG(p_f, "\n");
    sys_usw_opf_fprint_alloc_used_info(lchip, p_usw_acl_master[lchip]->opf_type_cid_ad, p_f);
    SYS_DUMP_DB_LOG(p_f, "\n");
    sys_usw_opf_fprint_alloc_used_info(lchip, p_usw_acl_master[lchip]->opf_type_udf, p_f);
    SYS_DUMP_DB_LOG(p_f, "\n");
    sys_usw_opf_fprint_alloc_used_info(lchip, p_usw_acl_master[lchip]->opf_type_aset, p_f);
    SYS_DUMP_DB_LOG(p_f, "\n");

    if(p_usw_acl_master[lchip]->vlan_edit_spool->count)
    {
        spool_cnt = 1;
        sal_memset(&param, 0, sizeof(param));
        param.data = (void*)p_f;
        param.data1 = (void*)&spool_cnt;
        param.value1 = lchip;

        SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n","Vlan edit spool");
        SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
        SYS_DUMP_DB_LOG(p_f, "%-8s%-8s%-8s%-8s%-8s%-8s%-8s%-8s%-8s%-8s%-12s%-12s%-12s\n","Node","StagOp","SvidSl","ScosSl","ScfiSl","CtagOp","CvidSl","CcosSl","CcfiSl", "TpidEn","TpidIdx","ProfileIdx","Refcnt");
        SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
        ctc_spool_traverse(p_usw_acl_master[lchip]->vlan_edit_spool, (spool_traversal_fn)_sys_usw_acl_dump_vlan_edit_spool_db , (void*)(&param));

    }
    if(p_usw_acl_master[lchip]->cid_spool->count)
    {
        spool_cnt = 1;
        sal_memset(&param, 0, sizeof(param));
        param.data = (void*)p_f;
        param.data1 = (void*)&spool_cnt;
        param.value1 = lchip;

        SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n","Cid ad spool");
        SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
        SYS_DUMP_DB_LOG(p_f, "DsCategoryIdPairHashRightAd/DsCategoryIdPairHashLeftAd\n");
        SYS_DUMP_DB_LOG(p_f, "%-12s%-20s%-20s%-20s\n", "Node","Table index", "Is left", "Ref count");
        SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
        ctc_spool_traverse(p_usw_acl_master[lchip]->cid_spool, (spool_traversal_fn)_sys_usw_acl_dump_cid_ad_spool_db , (void*)(&param));
    }
    if(p_usw_acl_master[lchip]->ad_spool->count)
    {
        spool_cnt = 1;
        sal_memset(&param, 0, sizeof(param));
        param.data = (void*)p_f;
        param.data1 = (void*)&spool_cnt;
        param.value1 = lchip;

        SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n","FlowHash ad spool");
        SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
        SYS_DUMP_DB_LOG(p_f, "DsFlow\n");
        SYS_DUMP_DB_LOG(p_f, "%-12s%-24s%-20s\n", "Node","Table index", "Ref count");
        SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
        ctc_spool_traverse(p_usw_acl_master[lchip]->ad_spool, (spool_traversal_fn)_sys_usw_acl_dump_hash_ad_spool_db , (void*)(&param));
    }
    loop = CTC_INGRESS;
    do
    {
        if(p_usw_acl_master[lchip]->cethertype_spool[0][loop] && p_usw_acl_master[lchip]->cethertype_spool[0][loop]->count)
        {
            spool_cnt = 1;
            sal_memset(&param, 0, sizeof(param));
            param.data = (void*)p_f;
            param.data1 = (void*)&spool_cnt;
            param.value1 = lchip;

            SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n","Compress ethertype spool");
            SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
            SYS_DUMP_DB_LOG(p_f, "ProgramAclEtherTypeCompressor\n");
            SYS_DUMP_DB_LOG(p_f, "%-12s%-24s%-20s\n", "Node","Table index", "Ref count");
            ctc_spool_traverse(p_usw_acl_master[lchip]->cethertype_spool[0][loop], (spool_traversal_fn)_sys_usw_acl_dump_cethertype_spool_db , (void*)(&param));

        }
    }while(++loop < CTC_BOTH_DIRECTION);
    loop = CTC_INGRESS;
    if(DRV_FROM_AT(lchip))
    {
        do
        {
            if(p_usw_acl_master[lchip]->cethertype_spool[1][loop] && p_usw_acl_master[lchip]->cethertype_spool[1][loop]->count)
            {
                spool_cnt = 1;
                sal_memset(&param, 0, sizeof(param));
                param.data = (void*)p_f;
                param.data1 = (void*)&spool_cnt;
                param.value1 = lchip;

                SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n"," Global Compress ethertype spool");
                SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
                SYS_DUMP_DB_LOG(p_f, "ProgramAclEtherTypeCompressor\n");
                SYS_DUMP_DB_LOG(p_f, "%-12s%-24s%-20s\n", "Node","Table index", "Ref count");
                ctc_spool_traverse(p_usw_acl_master[lchip]->cethertype_spool[1][loop], (spool_traversal_fn)_sys_usw_acl_dump_cethertype_spool_db , (void*)(&param));

            }
        }while(++loop < CTC_BOTH_DIRECTION);
    }
    loop = CTC_INGRESS;

    SYS_DUMP_DB_LOG(p_f, "\n");
    SYS_DUMP_DB_LOG(p_f, "Ofb type: %s\n","Cid");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
    sys_usw_ofb_dump_db(lchip, p_usw_acl_master[lchip]->ofb_type_cid, p_f);

    spool_cnt = 1;
    sal_memset(&param, 0, sizeof(param));
    param.data = (void*)p_f;
    param.data1 = (void*)&spool_cnt;
    param.value1 = lchip;
    SYS_DUMP_DB_LOG(p_f, "\n");
    SYS_DUMP_DB_LOG(p_f, "Flex Key.\n");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-12s%-12s%-12s%-12s\n", "Index", "key_type", "key_size", "presel_cnt/bmp");
    SYS_DUMP_DB_LOG(p_f, "%-12sblock:ltid ref_cnt\n", " ");
    ctc_vector_traverse(p_usw_acl_master[lchip]->flex_key_vec, (vector_traversal_fn)_sys_usw_acl_dump_flex_key_db, (void*)(&param));

    sal_memset(&param, 0, sizeof(param));
    param.data = (void*)p_f;
    param.value1 = lchip;
    SYS_DUMP_DB_LOG(p_f, "\n");
    SYS_DUMP_DB_LOG(p_f, "Aset.\n");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-12s%-12s%-12s%-12s\n", "aset_id", "type", "is_static", "ref_cnt");
    ctc_vector_traverse(p_usw_acl_master[lchip]->aset_vec, (vector_traversal_fn)_sys_usw_acl_dump_aset_db, (void*)(&param));

    SYS_DUMP_DB_LOG(p_f, "%s\n", "}");

    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}
int32
sys_usw_acl_set_action_priority(uint8 lchip, uint8 block_id, uint8 action_pri)
{
    int32 ret = 0;
    sys_acl_block_t* pb_tmp;
    ctc_fpa_block_t* pfab;
    uint32 cmd = 0;
    IpeAclGlobalActionPriorityCtl_m control;
    sys_acl_block_t* pb;
    uint32 hw_action_pri;
    uint32 dft_action_pri = 0;
    uint32 act_prio_table[CTC_BOTH_DIRECTION] = {IpeAclGlobalActionPriorityCtl_t, EpeAclGlobalActionPriorityCtl_t};
    uint8  dir = CTC_INGRESS;
    uint8  block_base = 0;

    SYS_ACL_INIT_CHECK();
    CTC_MAX_VALUE_CHECK(action_pri, 31);

    if(!DRV_FROM_TMM(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }
    SYS_USW_ACL_LOCK(lchip);
    if(p_usw_acl_master[lchip]->league[block_id].hdr_block_id != block_id)
    {
        ret = CTC_E_INVALID_PARAM;
    }
    if(block_id >= ACL_IGS_BLOCK_MAX_NUM)
    {
        dir = CTC_EGRESS;
        dft_action_pri = ACL_EGS_BLOCK_MAX_NUM - (block_id - ACL_IGS_BLOCK_MAX_NUM);
        block_base = ACL_IGS_BLOCK_MAX_NUM;
    }
    else
    {
        dir = CTC_INGRESS;
        dft_action_pri = ACL_IGS_BLOCK_MAX_NUM - block_id;
        block_base = 0;
    }
    if((DRV_IS_TMG(lchip) || DRV_IS_TMM(lchip)) && CTC_EGRESS == dir)
    {
        dft_action_pri = 0;
    }
    hw_action_pri = action_pri? action_pri : dft_action_pri;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_BLOCK, 1);
    pb = &SYS_ACL_BLOCK(lchip, block_id);
    {
        cmd = DRV_IOR(act_prio_table[dir], DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &control), ret, error1);
        pfab = &pb->fpab;
        do
        {
            pb_tmp = _ctc_container_of(pfab, sys_acl_block_t, fpab);
            do
            {
                SetIpeAclGlobalActionPriorityCtl(V, gLookup_0_actionPriority_f + pb_tmp->block_id - block_base, &control, hw_action_pri);
                pb_tmp = pb_tmp->next;
            }while(pb_tmp);
            pfab = pfab->next;
        }while(pfab);
        cmd = DRV_IOW(act_prio_table[dir], DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &control) , ret, error1);
    }
error1:
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_get_action_priority(uint8 lchip, uint8 block_id, uint8* p_action_pri)
{
    int32 ret = 0;
    uint32 cmd = 0;
    IpeAclGlobalActionPriorityCtl_m control;
    uint32 act_prio_table[CTC_BOTH_DIRECTION] = {IpeAclGlobalActionPriorityCtl_t, EpeAclGlobalActionPriorityCtl_t};
    uint8  lkup_level = block_id;
    uint8  dir = CTC_INGRESS;

    SYS_ACL_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_action_pri);
    if(!DRV_FROM_TMM(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }

    SYS_USW_ACL_LOCK(lchip);
    if(block_id >= ACL_IGS_BLOCK_MAX_NUM)
    {
        dir = CTC_EGRESS;
        lkup_level = block_id-ACL_IGS_BLOCK_MAX_NUM;
    }
    else
    {
        dir = CTC_INGRESS;
    }

    cmd = DRV_IOR(act_prio_table[dir], DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &control), ret, error1);

    *p_action_pri = GetIpeAclGlobalActionPriorityCtl(V, gLookup_0_actionPriority_f + lkup_level, &control);

error1:
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

#define SYS_WB_APPID(lchip, modid, subid)   (((lchip)<<16) | CTC_WB_APPID(modid, subid))
int32
_sys_usw_acl_wb_init(uint8 lchip)
{
    ctc_wb_appid_t  appid;
    uint8 has_flex_key = 0;
    sal_memset(&appid,0,sizeof(appid));

    appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MASTER) ;
    appid.entry_num = SYS_WB_FEATURE_MASTER_NUM;
    appid.entry_size  = sizeof(sys_wb_acl_master_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_GROUP) ;
    appid.entry_num = SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_ACL_GROUP);
    appid.entry_size  = sizeof(sys_wb_acl_group_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_ENTRY) ;
    appid.entry_num = SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_ACL);
    appid.entry_size  = sizeof(sys_wb_acl_tcam_entry_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_HASH_ENTRY) ;
    appid.entry_num = SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_ACL_FLOW);
    appid.entry_size  = sizeof(sys_wb_acl_hash_entry_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_TCAM_CID) ;
    appid.entry_num = MCHIP_CAP(SYS_CAP_ACL_TCAM_CID_PAIR);
    appid.entry_size  = sizeof(sys_wb_ofb_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_BLOCK) ;
    appid.entry_num = MCHIP_CAP(SYS_CAP_ACL_INGRESS_LKUP_NUM) + MCHIP_CAP(SYS_CAP_ACL_EGRESS_LKUP_NUM);
    appid.entry_size  = sizeof(sys_wb_acl_block_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_UDF_ENTRY) ;
    appid.entry_num = DRV_TABLE_MAX_INDEX(lchip, ParserUdfCamResult1_t);
    appid.entry_size  = sizeof(sys_wb_acl_udf_entry_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

   if(DRV_FROM_TMM(lchip))
    {
       appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_LT_BLOCK) ;
       appid.entry_num = DRV_TABLE_MAX_INDEX(lchip, DsLtidSelectTcam_t);
       appid.entry_size  = sizeof(sys_wb_acl_lt_block_t);
       appid.rt_en = 0;
       ctc_wb_add_appid( lchip, &appid);

       appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_PRESEL) ;
       appid.entry_num = DRV_TABLE_MAX_INDEX(lchip, DsLtidSelectTcam_t);
       appid.entry_size  = sizeof(sys_wb_acl_presel_t);
       appid.rt_en = 0;
       ctc_wb_add_appid( lchip, &appid);

       has_flex_key = 1;
    }
    appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_FLEX_KEY) ;
    appid.entry_num = ((CTC_ACL_KEY_FLEX_END - CTC_ACL_KEY_FLEX_BASE) << has_flex_key);
    appid.entry_size  = sizeof(sys_wb_acl_flex_key_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    appid.app_id = SYS_WB_APPID(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_ASET) ;
    appid.entry_num = (SYS_ACL_ASET_MAX+1);
    appid.entry_size  = sizeof(sys_wb_acl_aset_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    return 0;
}

#define _ACL_INIT_

STATIC int32
_sys_usw_acl_free_vec_node_data(void* node_data, void* user_data)
{
    mem_free(node_data);
    return CTC_E_NONE;
}

int32
sys_usw_acl_kset_init(uint8 lchip)
{
    uint8 loop = 0;
    sys_acl_kset_t* p_kset = NULL;
    uint8 drv_chip = drv_get_chip_type(lchip);

#define SYS_ACL_DEF_KK(DTYPE, STYPE)    p_usw_acl_master[lchip]->kset_db[DTYPE] = p_usw_acl_master[lchip]->kset_db[STYPE];
#define SYS_ACL_DEF_E(TYPE)             p_usw_acl_master[lchip]->kset_db[TYPE] = NULL;
#define SYS_ACL_DEF_K(TYPE)             p_kset = p_usw_acl_master[lchip]->kset_db[TYPE];
#define SYS_ACL_DEF_F(UNBMP, FIELD)       !CTC_IS_BIT_SET(UNBMP, drv_chip) ? SYS_ACL_PKSET_ADD(p_kset, FIELD) : SYS_ACL_PKSET_REMOVE(p_kset, FIELD);

    p_kset = mem_malloc(MEM_ACL_MODULE, CTC_ACL_KEY_FLEX_BASE*sizeof(sys_acl_kset_t));
    if (NULL == p_kset)
    {
        return CTC_E_NO_MEMORY;
    }
    for (loop=0; loop<CTC_ACL_KEY_FLEX_BASE; loop++)
    {
        p_usw_acl_master[lchip]->kset_db[loop] = &p_kset[loop];
    }

    if (DRV_FROM_TMM(lchip))
    {
        #include "tsingma_mx/sys_tmm_acl_kset.h"
    }
    else
    {
        #include "sys_usw_acl_kset.h"
    }
    return CTC_E_NONE;
}

int32
sys_usw_acl_fpa_block_init(uint8 lchip, uint8 block_id)
{
    uint32 size = 0;
    uint16 start_offset = 0;
    uint8  lkup_level = 0;
    uint8  dir = 0;
    uint8  chip_index = 0;  /*TMM use 1, others use 0*/
    uint8  resrc_index = 0;
    #if 0
    uint8  key_size_cnt[2][4] = {   /*size based on k80*/
            {1, 4, 32, 64},
            {1, 2, 12, 4}
        };
    #endif
#if !defined(EMULATION_ENV) || defined(EMULATOR_ENV)
    uint32 key_id[][2] = {
            {DsAclQosKey80Ing0_t,        DsAclQosKey80Egr0_t},
            {DsProgrammingAclTcam0_t,    DsAclQosL3Key160Egr0_t},
            {DsProgrammingAclTcam0_t,    DsEgrProgrammingAclTcam0_t}
        };
#endif
    uint32 pb_sz = 0;
    ctc_fpa_block_t *pb = NULL;
    sys_acl_block_t *p_acl_block = NULL;
    sys_acl_league_t *p_sys_league = NULL;
    sys_acl_fpa_ecnt_t fpa_ecnt;

    lkup_level = (block_id >= ACL_IGS_BLOCK_MAX_NUM)? (block_id - ACL_IGS_BLOCK_MAX_NUM) : block_id;
    dir = (block_id >= ACL_IGS_BLOCK_MAX_NUM)? CTC_EGRESS: CTC_INGRESS;
    if (DRV_FROM_AT(lchip))
    {
        chip_index = 2;
        resrc_index = 1;
    }
    else if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
    {
        chip_index = 1;
        resrc_index = ( dir == CTC_INGRESS? 1: 0 );
    }
    else
    {
        chip_index = resrc_index = 0;
    }

#if defined(EMULATION_ENV) && !defined(EMULATOR_ENV)
    pb_sz = 32;
    chip_index = chip_index;
#else
    ACL_GET_TABLE_ENTYR_NUM(lchip, key_id[chip_index][dir] + lkup_level, &pb_sz);
#endif
    if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && (dir == CTC_EGRESS))
    {
        pb_sz = pb_sz << 1;
    }
    size = sizeof(ctc_fpa_entry_t*) * pb_sz;
    p_acl_block = &SYS_ACL_BLOCK(lchip, block_id);
    sal_memset(p_acl_block, 0, sizeof(sys_acl_block_t));
    pb = &p_acl_block->fpab;
    p_acl_block->group_list = ctc_slist_new();
    if(NULL == p_acl_block->group_list)
    {
        return CTC_E_NO_MEMORY;
    }
    p_acl_block->entry_num = pb_sz;
    p_acl_block->block_id = block_id;
    p_acl_block->block_status = SYS_ACL_BLOCK_STATUS_UNMERGE;
    pb->entry_count = pb_sz;
    pb->free_count  = pb_sz;

    pb->same_size = resrc_index;
    pb->part_num = 1;

    #if 0
    start_offset = 0;
    pb->start_offset[CTC_FPA_KEY_SIZE_80]    = start_offset;
    pb->sub_entry_count[CTC_FPA_KEY_SIZE_80] = 0;
    pb->sub_free_count[CTC_FPA_KEY_SIZE_80]  = 0;
    pb->sub_rsv_count[CTC_FPA_KEY_SIZE_80]   = 0;
    start_offset = 0;
    pb->start_offset[CTC_FPA_KEY_SIZE_160]    = start_offset;
    pb->sub_entry_count[CTC_FPA_KEY_SIZE_160] = pb_sz / key_size_cnt[resrc_index][CTC_FPA_KEY_SIZE_160];
    pb->sub_free_count[CTC_FPA_KEY_SIZE_160]  = pb_sz / key_size_cnt[resrc_index][CTC_FPA_KEY_SIZE_160];
    pb->sub_rsv_count[CTC_FPA_KEY_SIZE_160]  = 0;
    start_offset += pb_sz / 2;
    pb->start_offset[CTC_FPA_KEY_SIZE_320]    = start_offset;
    pb->sub_entry_count[CTC_FPA_KEY_SIZE_320] = pb_sz*3 / key_size_cnt[resrc_index][CTC_FPA_KEY_SIZE_320];
    pb->sub_free_count[CTC_FPA_KEY_SIZE_320]  = pb_sz*3 / key_size_cnt[resrc_index][CTC_FPA_KEY_SIZE_320];
    pb->sub_rsv_count[CTC_FPA_KEY_SIZE_320]  = 0;
    start_offset += resrc_index? (pb_sz/4) : (pb_sz*3/8);
    pb->start_offset[CTC_FPA_KEY_SIZE_640]    = start_offset;
    pb->sub_entry_count[CTC_FPA_KEY_SIZE_640] = pb_sz / key_size_cnt[resrc_index][CTC_FPA_KEY_SIZE_640];
    pb->sub_free_count[CTC_FPA_KEY_SIZE_640]  = pb_sz / key_size_cnt[resrc_index][CTC_FPA_KEY_SIZE_640];
    pb->sub_rsv_count[CTC_FPA_KEY_SIZE_640]  = 0;
    #else
    if (1 == pb->same_size)
    {
        start_offset = 0;
        pb->start_offset[CTC_FPA_KEY_SIZE_80]    = 0;
        pb->sub_entry_count[CTC_FPA_KEY_SIZE_80] = 0;
        pb->sub_free_count[CTC_FPA_KEY_SIZE_80]  = 0;
        pb->sub_rsv_count[CTC_FPA_KEY_SIZE_80]   = 0;
        start_offset = 0;
        pb->start_offset[CTC_FPA_KEY_SIZE_160]    = start_offset;
        pb->sub_entry_count[CTC_FPA_KEY_SIZE_160] = pb_sz / 2;
        pb->sub_free_count[CTC_FPA_KEY_SIZE_160]  = pb_sz / 2;
        pb->sub_rsv_count[CTC_FPA_KEY_SIZE_160]   = 0;
        start_offset += pb_sz / 2;
        pb->start_offset[CTC_FPA_KEY_SIZE_320]    = start_offset;
        pb->sub_entry_count[CTC_FPA_KEY_SIZE_320] = pb_sz / 4;
        pb->sub_free_count[CTC_FPA_KEY_SIZE_320]  = pb_sz / 4;
        pb->sub_rsv_count[CTC_FPA_KEY_SIZE_320]   = 0;
        start_offset += pb_sz / 4;
        pb->start_offset[CTC_FPA_KEY_SIZE_640]    = start_offset;
        pb->sub_entry_count[CTC_FPA_KEY_SIZE_640] = pb_sz / 4;
        pb->sub_free_count[CTC_FPA_KEY_SIZE_640]  = pb_sz / 4;
        pb->sub_rsv_count[CTC_FPA_KEY_SIZE_640]   = 0;
    }
    else
    {
        sys_usw_acl_split_fpa_block(lchip, pb_sz, fpa_ecnt);
        pb->sub_rsv_count[CTC_FPA_KEY_SIZE_640]   = 0;
        pb->sub_entry_count[CTC_FPA_KEY_SIZE_640] = fpa_ecnt[CTC_FPA_KEY_SIZE_640] >> 3;
        pb->sub_free_count[CTC_FPA_KEY_SIZE_640]  = pb->sub_entry_count[CTC_FPA_KEY_SIZE_640];
        pb->start_offset[CTC_FPA_KEY_SIZE_640]    = pb_sz - fpa_ecnt[CTC_FPA_KEY_SIZE_640];

        pb->sub_rsv_count[CTC_FPA_KEY_SIZE_320]   = 0;
        pb->sub_entry_count[CTC_FPA_KEY_SIZE_320] = fpa_ecnt[CTC_FPA_KEY_SIZE_320] >> 2;
        pb->sub_free_count[CTC_FPA_KEY_SIZE_320]  = pb->sub_entry_count[CTC_FPA_KEY_SIZE_320];
        pb->start_offset[CTC_FPA_KEY_SIZE_320]    = fpa_ecnt[CTC_FPA_KEY_SIZE_160];

        pb->sub_rsv_count[CTC_FPA_KEY_SIZE_160]   = 0;
        pb->sub_entry_count[CTC_FPA_KEY_SIZE_160] = fpa_ecnt[CTC_FPA_KEY_SIZE_160] >> 1;
        pb->sub_free_count[CTC_FPA_KEY_SIZE_160]  = pb->sub_entry_count[CTC_FPA_KEY_SIZE_160];
        pb->start_offset[CTC_FPA_KEY_SIZE_160]    = 0;

        start_offset = 0;
        pb->start_offset[CTC_FPA_KEY_SIZE_80]    = 0;
        pb->sub_entry_count[CTC_FPA_KEY_SIZE_80] = 0;
        pb->sub_free_count[CTC_FPA_KEY_SIZE_80]  = 0;
        pb->sub_rsv_count[CTC_FPA_KEY_SIZE_80]   = 0;
    }
    #endif

    /* init acl lookup level merge bitmap */
    p_sys_league = &(p_usw_acl_master[lchip]->league[block_id]);
    p_sys_league->block_id = block_id;
    p_sys_league->lkup_level_bitmap = 0;
    CTC_BIT_SET(p_sys_league->lkup_level_bitmap, lkup_level);
    p_sys_league->lkup_level_start[lkup_level] = 0;
    p_sys_league->lkup_level_count[lkup_level] = pb_sz;
    p_sys_league->merged_to = block_id;
    p_sys_league->hdr_block_id = block_id;
    p_sys_league->size = 0;

    if(0 == size)
    {
        return CTC_E_NONE;
    }
    MALLOC_ZERO(MEM_ACL_MODULE, pb->entries, size);
    if ((NULL == pb->entries) && size)
    {
        ctc_slist_delete(p_acl_block->group_list);
        p_acl_block->group_list = NULL;
        return CTC_E_NO_MEMORY;
    }
    return CTC_E_NONE;
}


/*Update ldp for nexthop ldp tunnel underlay change*/
#if 1
int32
_sys_usw_acl_update_ldp_dsacl(uint8 lchip, sys_com_ldp_update_t* p_param)
{
    ctc_list_pointer_node_t * node;
    sys_acl_entry_t * pe;
    sys_acl_ldp_entry_t* pe_ldp = NULL;
    uint32 cmd = 0;
    uint32 key_id = 0;
    uint32 act_id = 0;
    uint32 ad_index = 0;
    uint32 hw_index = 0;
    uint8 step = 0;
    uint8 global_pp_en = 0;
    ds_t dsacl;
    sys_com_ldp_node_t ldp_node;
    sys_com_ldp_node_t* p_ldp_node = NULL;

    SYS_USW_ACL_LOCK(lchip);

    ldp_node.ldp = p_param->ldp;
    p_ldp_node = ctc_hash_lookup(p_usw_acl_master[lchip]->ldp_hash, &ldp_node);
    if (NULL == p_ldp_node)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NONE;
    }

    CTC_LIST_POINTER_LOOP(node, &p_ldp_node->update_list)
    {
        pe_ldp = _ctc_container_of(node, sys_acl_ldp_entry_t, ldp_node);
        _sys_usw_acl_get_nodes_by_eid(lchip, pe_ldp->entry_id, &pe, NULL, NULL);
        if (!pe)
        {
            continue;
        }

        if (FPA_ENTRY_FLAG_INSTALLED == pe->fpae.flag )
        {
            global_pp_en = SYS_ACL_IS_GLOBAL_PP_EN_LKUP(lchip, pe->group->group_info.dir, pe->group->group_info.block_id);
            if (SYS_ACL_GROUP_IS_PRESEL(pe->group)&& ACL_ENTRY_IS_TCAM(pe))
            {

                SYS_ACL_GET_TBL_FUNC(lchip, pe, &key_id, &act_id, &hw_index);
                _sys_usw_acl_get_key_size(lchip, 1, pe, &step);
                ad_index = SYS_ACL_MAP_DRV_AD_INDEX(hw_index, step);

                cmd = DRV_IOR(act_id, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, ad_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), dsacl);

                if (p_param->ecmp_gid || p_param->ul_nh_en)
                {
                    SetDsAcl(V, u1_g2_adDestMap_f, &dsacl, (p_param->ecmp_gid | (p_param->ul_nh_en<<12)));
                    SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &dsacl, 1);
                }
                else
                {
                    SetDsAcl(V, u1_g2_adDestMap_f, &dsacl, p_param->destmap);
                    SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &dsacl, 0);
                }
                cmd = DRV_IOW(act_id, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, ad_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL) && !global_pp_en), dsacl);

            }
            else if(ACL_ENTRY_IS_TCAM(pe))
            {
                SYS_ACL_GET_TBL_FUNC(lchip, pe, &key_id, &act_id, &hw_index);
                _sys_usw_acl_get_key_size(lchip, 1, pe, &step);
                ad_index = SYS_ACL_MAP_DRV_AD_INDEX(hw_index, step);

                cmd = DRV_IOR(act_id, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, ad_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), dsacl);
                if (p_param->ecmp_gid || p_param->ul_nh_en)
                {
                    SetDsAcl(V, u1_g2_adDestMap_f, &dsacl, (p_param->ecmp_gid | (p_param->ul_nh_en<<12)));
                    SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &dsacl, 1);
                }
                else
                {
                    SetDsAcl(V, u1_g2_adDestMap_f, &dsacl, p_param->destmap);
                    SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &dsacl, 0);
                }
                cmd = DRV_IOW(act_id, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, ad_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL) && !global_pp_en), dsacl);
            }
        }
        else
        {
            if (p_param->ecmp_gid || p_param->ul_nh_en)
            {
                SetDsAcl(V, u1_g2_adDestMap_f, &pe->ua->buffer.action, (p_param->ecmp_gid | (p_param->ul_nh_en<<12)));
                SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &pe->ua->buffer.action, 1);
            }
            else
            {
                SetDsAcl(V, u1_g2_adDestMap_f, &pe->ua->buffer.action, p_param->destmap);
                SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &pe->ua->buffer.action, 0);
            }
        }

        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "update DsAcl adIndex:%d, destmap:0x%x, ecmpGid:%d\n",
            pe->fpae.offset_a, p_param->destmap, p_param->ecmp_gid);
    }

    SYS_USW_ACL_UNLOCK(lchip);

    return 0;
}


int32
sys_usw_acl_update_ldp_dsacl(uint8 lchip, sys_com_ldp_update_t* p_param)
{
    uint8 lchip_start              = 0;
    uint8 lchip_end                = 0;
    uint8 all_chip = 1;

    CTC_AT_FOREACH_LCHIP2(lchip_start, lchip_end, all_chip, CTC_FEATURE_ACL)
    {
        _sys_usw_acl_update_ldp_dsacl(lchip, p_param);
    }
    return CTC_E_NONE;
}

int32
_sys_usw_acl_update_dsacl_by_nhid(uint8 lchip, sys_com_ldp_update_t* p_param)
{
    ctc_list_pointer_node_t * node;
    ctc_list_pointer_node_t * node_next;
    sys_acl_entry_t * pe;
    sys_acl_ldp_entry_t * pe_ldp = NULL;
    uint32 cmd = 0;
    uint32 key_id = 0;
    uint32 act_id = 0;
    uint32 ad_index = 0;
    uint32 hw_index = 0;
    uint8 step = 0;
    uint8 global_pp_en = 0;
    ds_t dsacl;
    sys_com_ldp_node_t ldp_node;
    sys_com_ldp_node_t* p_ldp_node = NULL;
    uint8 update_ldp = DRV_FROM_AT(lchip) && p_param->ldp && !p_param->bind_ldp;

    SYS_USW_ACL_LOCK(lchip);

    ldp_node.ldp = p_param->nhid;
    p_ldp_node = ctc_hash_lookup(p_usw_acl_master[lchip]->nhid_hash, &ldp_node);
    if (NULL == p_ldp_node)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NONE;
    }

    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "update DsAcl nhid:%u, destmap:0x%x, ecmpGid:%d\n", p_param->nhid, p_param->destmap, p_param->ecmp_gid);
    CTC_LIST_POINTER_LOOP(node, &p_ldp_node->update_list)
    {
        uint32 ldp = 0;
        pe_ldp = _ctc_container_of(node, sys_acl_ldp_entry_t, nhid_list_node);
        _sys_usw_acl_get_nodes_by_eid(lchip, pe_ldp->entry_id, &pe, NULL, NULL);

        SYS_ACL_GET_LDP(ldp, pe);
        if (ldp != p_param->ldp)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "move dsacl from ldp %u to ldp %u\n", ldp, p_param->ldp);
            if (ldp)
            {
                sys_usw_remove_ldp_node(lchip, p_usw_acl_master[lchip]->ldp_hash, ldp, &pe_ldp->ldp_node);
            }

            if (p_param->ldp)
            {
                if(0 == pe->ua_type && pe->ua)
                {
                    pe->ua->buffer.ad.tcam.ldp = p_param->ldp;
                }
                else if(pe->ua && SYS_ACL_AD_TYPE_DISABLE == pe->ad_type)
                {
                    pe->ua->ad.ldp = p_param->ldp;
                }
                sys_usw_add_ldp_node(lchip, p_usw_acl_master[lchip]->ldp_hash, p_param->ldp, &pe_ldp->ldp_node);
            }
        }
        if (FPA_ENTRY_FLAG_INSTALLED == pe->fpae.flag )
        {
            global_pp_en = SYS_ACL_IS_GLOBAL_PP_EN_LKUP(lchip, pe->group->group_info.dir, pe->group->group_info.block_id);
            if (SYS_ACL_GROUP_IS_PRESEL(pe->group)&& ACL_ENTRY_IS_TCAM(pe))
            {

                SYS_ACL_GET_TBL_FUNC(lchip, pe, &key_id, &act_id, &hw_index);
                _sys_usw_acl_get_key_size(lchip, 1, pe, &step);
                ad_index = SYS_ACL_MAP_DRV_AD_INDEX(hw_index, step);

                cmd = DRV_IOR(act_id, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, ad_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL) && !global_pp_en), dsacl);

                if (update_ldp)
                {
                    SetDsAcl(V, u2_gI2eSrcCid_i2eSrcCid_f, &dsacl, p_param->ldp);
                    SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &dsacl, 1);
                }
                else if (p_param->ecmp_gid)
                {
                    SetDsAcl(V, u1_g2_adDestMap_f, &dsacl, p_param->ecmp_gid);
                    SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &dsacl, 1);
                }
                else
                {
                    SetDsAcl(V, u1_g2_adDestMap_f, &dsacl, p_param->destmap);
                    SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &dsacl, 0);
                }
                if (p_param->dsnh_valid)
                {
                    SetDsAcl(V, u1_g2_adNextHopPtr_f, &dsacl, p_param->dsnh_offset);
                    SetDsAcl(V, u1_g2_adBypassIngressEdit_f, &dsacl, p_param->bypass_igr_edit);
                    SetDsAcl(V, u1_g2_adNextHopExt_f, &dsacl, p_param->nexthop_ext);
                }
                cmd = DRV_IOW(act_id, DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, ad_index, DRV_CMD_BMP_EN(cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL) && !global_pp_en), dsacl);
            }
        }
        else if(pe->ua)
        {
            if (update_ldp)
            {
                SetDsAcl(V, u2_gI2eSrcCid_i2eSrcCid_f, &dsacl, p_param->ldp);
                SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &dsacl, 1);
            }
            else if (p_param->ecmp_gid)
            {
                SetDsAcl(V, u1_g2_adDestMap_f, &pe->ua->buffer.action, p_param->ecmp_gid);
                SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &pe->ua->buffer.action, 1);
            }
            else
            {
                SetDsAcl(V, u1_g2_adDestMap_f, &pe->ua->buffer.action, p_param->destmap);
                SetDsAcl(V, u1_g2_ecmpTunnelMode_f, &pe->ua->buffer.action, 0);
            }
            if (p_param->dsnh_valid)
            {
                SetDsAcl(V, u1_g2_adNextHopPtr_f, &pe->ua->buffer.action, p_param->dsnh_offset);
                SetDsAcl(V, u1_g2_adBypassIngressEdit_f, &pe->ua->buffer.action, p_param->bypass_igr_edit);
                SetDsAcl(V, u1_g2_adNextHopExt_f, &pe->ua->buffer.action, p_param->nexthop_ext);
            }
        }

        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "update DsAcl adIndex:%d, destmap:0x%x, ecmpGid:%d\n",
            pe->fpae.offset_a, p_param->destmap, p_param->ecmp_gid);
    }

    if (p_param->is_del)
    {
        CTC_LIST_POINTER_LOOP_DEL(node, node_next, &p_ldp_node->update_list)
        {
            pe_ldp = _ctc_container_of(node, sys_acl_ldp_entry_t, nhid_list_node);
            _sys_usw_acl_get_nodes_by_eid(lchip, pe_ldp->entry_id, &pe, NULL, NULL);
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "remove acl dsacl %u from nhid %u\n", pe->fpae.offset_a, p_param->nhid);
            sys_usw_remove_ldp_node(lchip, p_usw_acl_master[lchip]->nhid_hash, p_param->nhid, &pe_ldp->nhid_list_node);
            if(0 == pe->ua_type && pe->ua)
            {
                pe->ua->buffer.ad.tcam.nexthop_id = 0;
            }
            else if(pe->ua && SYS_ACL_AD_TYPE_DISABLE == pe->ad_type)
            {
                pe->ua->ad.nexthop_id = 0;
            }
        }
    }

    SYS_USW_ACL_UNLOCK(lchip);

    return CTC_E_NONE;
}


int32
sys_usw_acl_update_dsacl_by_nhid(uint8 lchip, sys_com_ldp_update_t* p_param)
{
    uint8 lchip_start              = 0;
    uint8 lchip_end                = 0;
    uint8 all_chip = 1;

    CTC_AT_FOREACH_LCHIP2(lchip_start, lchip_end, all_chip, CTC_FEATURE_ACL)
    {
        _sys_usw_acl_update_dsacl_by_nhid(lchip, p_param);
    }
    return CTC_E_NONE;
}
#endif
/*
 * init acl module
 */

int32
sys_usw_acl_build_flow_hash_default_entry(uint8 lchip, uint16 lport, uint8 is_add)
{
    int32 ret = CTC_E_NONE;
    SYS_USW_ACL_LOCK(lchip);
    ret = _sys_usw_acl_build_flow_hash_default_entry(lchip, lport, is_add);
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_init(uint8 lchip, ctc_acl_global_cfg_t* acl_global_cfg)
{
    int32 ret = CTC_E_NONE;
    uint8       idx1 = 0;
    uint8       block_id = 0;
    //uint8       lkup_level = 0;
    //uint16      start_offset = 0;
    //uint32      size = 0;
    uint8       max_block_num = 0;
    uint8       field_range_num = 0;
    uint32      mem_size = 0;
    uint32      pb_sz[ACL_IGS_BLK_MAX_NUM+ACL_EGS_BLK_MAX_NUM] = {0};
    uint32      entry_num = 0;
    uint32      igs_key_id = 0, egs_key_id = 0;
    uint8       egs_fpa_size_80 = 0;
    uint8       bind_ldp_en = 0;
    //sys_acl_league_t* p_sys_league = NULL;
    sys_acl_field_range_t* p_field_range = NULL;
    drv_ftm_info_detail_t ftm_info;

    CTC_PTR_VALID_CHECK(acl_global_cfg);
    LCHIP_CHECK(lchip);


    /* check init */
    if (p_usw_acl_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT(lchip, p_usw_acl_master, CTC_FEATURE_ACL);

    max_block_num = MCHIP_CAP(SYS_CAP_ACL_INGRESS_LKUP_NUM) + MCHIP_CAP(SYS_CAP_ACL_EGRESS_LKUP_NUM);
    field_range_num = DRV_FROM_AT(lchip) ? 3 : (DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) ? 2 : 1;
    /* malloc master */
    mem_size = sizeof(sys_acl_master_t);
    mem_size += max_block_num * sizeof(sys_acl_block_t);
    mem_size += max_block_num * sizeof(sys_acl_league_t);
    mem_size += field_range_num * sizeof(sys_acl_field_range_t);
    mem_size += DRV_FROM_TMM(lchip) ? max_block_num * sizeof(sys_acl_lt_block_t) : 0;
    MALLOC_ZERO(MEM_ACL_MODULE, p_usw_acl_master[lchip], mem_size);
    if (NULL == p_usw_acl_master[lchip])
    {
        SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    p_usw_acl_master[lchip]->no_aset = DRV_FROM_AT(lchip) ? 0 : 1;
    p_usw_acl_master[lchip]->block = (void*)((uint8*)p_usw_acl_master[lchip] + sizeof(sys_acl_master_t));
    p_usw_acl_master[lchip]->league = (void*)((uint8*)p_usw_acl_master[lchip]->block + max_block_num * sizeof(sys_acl_block_t));
    
    if(SYS_VCHIP_PP_IS_NOT_BASE(lchip))
    {
        p_usw_acl_master[lchip]->field_range[0] = p_usw_acl_master[SYS_PP_BASE(lchip)]->field_range[0];
        p_usw_acl_master[lchip]->field_range[1] = p_usw_acl_master[SYS_PP_BASE(lchip)]->field_range[1];
        p_usw_acl_master[lchip]->field_range[2] = p_usw_acl_master[SYS_PP_BASE(lchip)]->field_range[2];
        p_usw_acl_master[lchip]->lt_block = (void*)((uint8*)p_usw_acl_master[lchip]->league + max_block_num * sizeof(sys_acl_league_t));
    }
    else
    {
        p_usw_acl_master[lchip]->field_range[0] = (void*)((uint8*)p_usw_acl_master[lchip]->league + max_block_num * sizeof(sys_acl_league_t));
        p_usw_acl_master[lchip]->field_range[1] = (field_range_num > 1) ?
                                                (void*)((uint8*)p_usw_acl_master[lchip]->field_range[0] + sizeof(sys_acl_field_range_t)) :
                                                p_usw_acl_master[lchip]->field_range[0];
        p_usw_acl_master[lchip]->field_range[2] = (field_range_num > 2) ?
                                                (void*)((uint8*)p_usw_acl_master[lchip]->field_range[1] + sizeof(sys_acl_field_range_t)) :
                                                p_usw_acl_master[lchip]->field_range[1];
        p_usw_acl_master[lchip]->lt_block = DRV_FROM_TMM(lchip) ?
                                            (void*)((uint8*)p_usw_acl_master[lchip]->field_range[2] + sizeof(sys_acl_field_range_t)) :
                                            NULL;                                
    }

    p_usw_acl_master[lchip]->igs_block_num = MCHIP_CAP(SYS_CAP_ACL_INGRESS_LKUP_NUM);
    p_usw_acl_master[lchip]->egs_block_num = MCHIP_CAP(SYS_CAP_ACL_EGRESS_LKUP_NUM);

    if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
    {
        p_usw_acl_master[lchip]->fixed_key_vec = ctc_vector_init(MCHIP_CAP(SYS_CAP_ACL_EGRESS_LKUP_NUM), CTC_ACL_KEY_FLEX_END - CTC_ACL_KEY_FLEX_BASE);
        CTC_ERROR_GOTO(sys_usw_acl_kset_init(lchip), ret, ERROR_FREE_MEM);
    }
    else if (!DRV_FROM_TMM(lchip))
    {
        p_usw_acl_master[lchip]->fixed_key_vec = ctc_vector_init(MCHIP_CAP(SYS_CAP_ACL_INGRESS_LKUP_NUM)+MCHIP_CAP(SYS_CAP_ACL_EGRESS_LKUP_NUM), CTC_ACL_KEY_FLEX_END - CTC_ACL_KEY_FLEX_BASE);
        CTC_ERROR_GOTO(sys_usw_acl_kset_init(lchip), ret, ERROR_FREE_MEM);
    }
    CTC_ERROR_GOTO(_sys_usw_acl_aset_init(lchip), ret, ERROR_FREE_MEM);

    p_usw_acl_master[lchip]->group = ctc_hash_create(SYS_ACL_USW_GROUP_HASH_SIZE/CTC_HASH_32_BLOCK_SIZE,
                                        CTC_HASH_32_BLOCK_SIZE,
                                        (hash_key_fn) _sys_usw_acl_hash_make_group,
                                        (hash_cmp_fn) _sys_usw_acl_hash_compare_group);

    /* init max priority */
    p_usw_acl_master[lchip]->max_entry_priority = CTC_ACL_ENTRY_PRIORITY_HIGHEST;
     _sys_usw_acl_install_build_key_fn(lchip);
     _sys_usw_acl_get_action_fn(lchip);
     p_usw_acl_master[lchip]->get_table_id_func[0] = (SYS_CB_ACL_GET_TBL_ID_FUNC_T) _sys_usw_acl_get_table_id;
     p_usw_acl_master[lchip]->get_table_id_func[1] = _sys_usw_acl_program_get_table_id;

    if (DRV_FROM_AT(lchip))
    {
        igs_key_id = DsProgrammingAclTcam0_t;
        egs_key_id = DsEgrProgrammingAclTcam0_t;
        egs_fpa_size_80 = 0;
    }
    else if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
    {
        igs_key_id = DsProgrammingAclTcam0_t;
        egs_key_id = DsAclQosMacKey160Egr0_t;
        egs_fpa_size_80 = 1;
    }
    else
    {
        igs_key_id = DsAclQosKey80Ing0_t;
        egs_key_id = DsAclQosMacKey160Egr0_t;
        egs_fpa_size_80 = 1;
    }

    /* init block_num_max */
    {
        for (block_id = 0; block_id < ACL_IGS_BLOCK_MAX_NUM; block_id++)
        {
            ACL_GET_TABLE_ENTYR_NUM(lchip, igs_key_id + block_id, &pb_sz[block_id]);

#if defined(EMULATION_ENV) && !defined(EMULATOR_ENV) /*EMULATION testing*/
            pb_sz[block_id] = 4;
#endif
        }

        for (block_id = 0; block_id < ACL_EGS_BLOCK_MAX_NUM; block_id++)
        {
            ACL_GET_TABLE_ENTYR_NUM(lchip, egs_key_id + block_id, &pb_sz[ACL_IGS_BLOCK_MAX_NUM + block_id]);
            pb_sz[ACL_IGS_BLOCK_MAX_NUM + block_id] = pb_sz[ACL_IGS_BLOCK_MAX_NUM + block_id] << egs_fpa_size_80;

#if defined(EMULATION_ENV) && !defined(EMULATOR_ENV) /*EMULATION testing*/
            pb_sz[ACL_IGS_BLOCK_MAX_NUM + block_id] = 4;
#endif

        }
    }
    if(!SYS_VCHIP_PP_IS_NOT_BASE(lchip))
    {
        p_field_range = p_usw_acl_master[lchip]->field_range[0];
        p_field_range->entry_num = p_field_range->free_num = 12;
        if (DRV_FROM_TMM(lchip))
        {
            p_field_range = p_usw_acl_master[lchip]->field_range[1];
            p_field_range->entry_num = p_field_range->free_num = 16;
            p_field_range->is_fg_rg = 1;
        }
        if (DRV_FROM_AT(lchip))
        {
            p_field_range = p_usw_acl_master[lchip]->field_range[2];
            p_field_range->entry_num = p_field_range->free_num = 16;
            p_field_range->is_fg_rg = 1;
        }
    }


    /* init sort algor / hash table  */
    {
        p_usw_acl_master[lchip]->fpa = fpa_usw_create(lchip,
                                                      _sys_usw_acl_get_block_by_pe_fpa,
                                                      _sys_usw_acl_entry_move_hw_fpa,
                                                      sizeof(ctc_slistnode_t));

        p_usw_acl_master[lchip]->entry = ctc_hash_create(SYS_ACL_USW_ENTRY_HASH_SIZE/CTC_HASH_1K_BLOCK_SIZE,
                                            CTC_HASH_1K_BLOCK_SIZE,
                                            (hash_key_fn) _sys_usw_acl_hash_make_entry,
                                            (hash_cmp_fn) _sys_usw_acl_hash_compare_entry);

        CTC_ERROR_GOTO((_sys_usw_acl_spool_init(lchip)), ret, ERROR_FREE_MEM);

        /*ACL ingress and egress, 4:3:1*/
        for (idx1 = 0; idx1 < ACL_IGS_BLOCK_MAX_NUM + ACL_EGS_BLOCK_MAX_NUM; idx1++)
        {
            CTC_ERROR_GOTO(sys_usw_acl_fpa_block_init(lchip, idx1), ret, ERROR_FREE_MEM);
        }

        if (!(p_usw_acl_master[lchip]->fpa &&
              p_usw_acl_master[lchip]->entry &&
              p_usw_acl_master[lchip]->ad_spool &&
              p_usw_acl_master[lchip]->vlan_edit_spool &&
              p_usw_acl_master[lchip]->cid_spool))
        {
            goto ERROR_FREE_MEM;
        }
    }
    if(DRV_FROM_AT(lchip))
    {
        p_usw_acl_master[lchip]->udf_mode = 0;/*[AT]:0:arctic mode;1:tmm mode;*/
    }
    else
    {
        p_usw_acl_master[lchip]->udf_mode = 1;/*[D2.TM.TMM]:must 1*/
    }
    p_usw_acl_master[lchip]->udf_entry = ctc_hash_create((MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM)+1)/CTC_HASH_16_BLOCK_SIZE,
                                        CTC_HASH_16_BLOCK_SIZE,
                                        (hash_key_fn) _sys_usw_acl_udf_hash_make_entry,
                                        (hash_cmp_fn) _sys_usw_acl_udf_hash_compare_entry);
    p_usw_acl_master[lchip]->udf_ad =ctc_vector_init(CTC_VEC_BLOCK_NUM(MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM) + MCHIP_CAP(SYS_CAP_ACL_SUDF_ENTRY_NUM), SYS_UDF_AD_VEC_BLK_SIZE), SYS_UDF_AD_VEC_BLK_SIZE);

    if (DRV_IS_DUET2(lchip) || DRV_IS_TSINGMA(lchip))
    {
        CTC_ERROR_GOTO(_sys_usw_acl_init_league_bitmap(lchip), ret, ERROR_FREE_MEM);
    }
    if(SYS_VCHIP_PP_IS_NOT_BASE(lchip))
    {
        p_usw_acl_master[lchip]->acl_mutex = p_usw_acl_master[SYS_PP_BASE(lchip)]->acl_mutex;
    }
    else
    {
        SYS_ACL_CREATE_LOCK(lchip);
    }

    CTC_ERROR_GOTO(_sys_usw_acl_init_global_cfg(lchip, acl_global_cfg), ret, ERROR_FREE_MEM);
    p_usw_acl_master[lchip]->upa_en = acl_global_cfg->upa_en;
    p_usw_acl_master[lchip]->udf_fpa_en = DRV_FROM_TMM(lchip) && acl_global_cfg->udf_fpa_en;

    if (!(CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING))
    {
        CTC_ERROR_GOTO(_sys_usw_acl_create_rsv_group(lchip), ret, ERROR_FREE_MEM);
    }

    CTC_ERROR_GOTO(_sys_usw_acl_opf_init(lchip), ret, ERROR_FREE_MEM);

    CTC_ERROR_GOTO(_sys_usw_acl_ofb_init(lchip), ret, ERROR_FREE_MEM);

    CTC_ERROR_GOTO(_sys_usw_acl_init_vlan_edit(lchip), ret, ERROR_FREE_MEM);

    if (MCHIP_ACL(lchip)->init)
    {
        CTC_ERROR_GOTO(MCHIP_ACL(lchip)->init(lchip), ret, ERROR_FREE_MEM);
    }


    /*init ldp hash*/
    CTC_ERROR_GOTO(sys_usw_nh_get_bind_ldp_en(lchip, &bind_ldp_en), ret, ERROR_FREE_MEM);
    if(DRV_FROM_TMM(lchip) || (DRV_IS_TSINGMA(lchip) && bind_ldp_en))
    {
            p_usw_acl_master[lchip]->ldp_hash = ctc_hash_create(SYS_ACL_LDP_HASH_NUM/CTC_HASH_256_BLOCK_SIZE, CTC_HASH_256_BLOCK_SIZE,
                                                        (hash_key_fn)sys_usw_ldp_hash_make,
                                                        (hash_cmp_fn)sys_usw_ldp_hash_cmp);
        if (!p_usw_acl_master[lchip]->ldp_hash)
        {
            ret =  CTC_E_NO_MEMORY;
            goto ERROR_FREE_MEM;
        }
    }
    if(p_usw_acl_master[lchip]->udf_fpa_en)
    {
        ctc_fpa_block_t* pb;
        p_usw_acl_master[lchip]->udf_fpa = fpa_usw_create(lchip,
                                                          _sys_usw_acl_udf_get_block_by_pe_fpa,
                                                          _sys_usw_acl_udf_move_hw_fpa, 0 );
        pb = &p_usw_acl_master[lchip]->udf_block.fpab;
        MALLOC_ZERO(MEM_ACL_MODULE, pb->entries, (MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM)+1)*sizeof(ctc_fpa_entry_t*));
        if (NULL == pb->entries)
        {
            ret = CTC_E_NO_MEMORY;
            goto ERROR_FREE_MEM;
        }

        /*tcam index is reserved*/
        pb->entry_count = MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM);
        pb->free_count  = MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM);

        pb->start_offset[CTC_FPA_KEY_SIZE_80]    = 1;
        pb->sub_entry_count[CTC_FPA_KEY_SIZE_80] = MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM);
        pb->sub_free_count[CTC_FPA_KEY_SIZE_80]  = MCHIP_CAP(SYS_CAP_ACL_UDF_ENTRY_NUM);
        pb->sub_rsv_count[CTC_FPA_KEY_SIZE_80]   = 0;

    }
    sys_usw_ftm_register_callback(lchip, CTC_FTM_SPEC_ACL, sys_usw_acl_ftm_acl_cb);
    sys_usw_ftm_register_callback(lchip, CTC_FTM_SPEC_ACL_FLOW, sys_usw_acl_ftm_acl_flow_cb);

    CTC_ERROR_GOTO(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_ACL, SYS_WB_APPID_ACL_SUBID_MAX,sys_usw_acl_wb_sync), ret, ERROR_FREE_MEM);

    /*capability*/
    sys_usw_ftm_query_table_entry_num(lchip, DsFlowL2HashKey_t, &entry_num);
    MCHIP_CAP(SYS_CAP_SPEC_ACL_HASH_ENTRY_NUM) = entry_num;
    MCHIP_CAP(SYS_CAP_SPEC_ACL_ENTRY_NUM) = entry_num;
    block_id = 0;
    do
    {
        sys_usw_ftm_query_table_entry_num(lchip, igs_key_id+block_id, &entry_num);
        MCHIP_CAP(SYS_CAP_SPEC_ACL0_IGS_TCAM_ENTRY_NUM+block_id) = entry_num;
        MCHIP_CAP(SYS_CAP_SPEC_ACL_ENTRY_NUM) += entry_num;
    }while( ++block_id<ACL_IGS_BLOCK_MAX_NUM );
    block_id = 0;
    do
    {
        sys_usw_ftm_query_table_entry_num(lchip, egs_key_id+block_id, &entry_num);
        MCHIP_CAP(SYS_CAP_SPEC_ACL0_EGS_TCAM_ENTRY_NUM+block_id) = entry_num << egs_fpa_size_80;
        MCHIP_CAP(SYS_CAP_SPEC_ACL_ENTRY_NUM) += entry_num << egs_fpa_size_80;
    }while( ++block_id<ACL_EGS_BLOCK_MAX_NUM );

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        CTC_ERROR_GOTO(sys_usw_acl_wb_restore(lchip), ret, ERROR_FREE_MEM);
    }
    if (CTC_WB_ENABLE(lchip))
    {
        CTC_ERROR_GOTO(_sys_usw_acl_wb_init(lchip), ret, ERROR_FREE_MEM);
    }

    CTC_ERROR_RETURN(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_ACL, sys_usw_acl_dump_db));

    if (MCHIP_XDATA(lchip)->func_en && !SYS_VCHIP_PP_IS_NOT_BASE(lchip))
    {
        CTC_ERROR_RETURN(MCHIP_XDATA(lchip)->func_en(lchip, SYS_XDATA_FUNC_FWD_TYPE, 1, NULL));
    }

    #if defined(TSINGMA_MX) || defined(TSINGMA_GX) || defined(ARCTIC)
    SYS_CB_REGISTER(lchip, SYS_CB_LDP_UPDATE_ACL, sys_usw_acl_update_ldp_dsacl);
    SYS_CB_REGISTER(lchip, SYS_CB_NHID_UPDATE_ACL, sys_usw_acl_update_dsacl_by_nhid);
    #endif

    #if defined(EMULATION_ENV) && !defined(EMULATOR_ENV)
    {
        uint8 emu_blk = 0, emu_idx;
        uint32 emu_cmd = 0;
        for (emu_blk=0; emu_blk<8; emu_blk++)
        {
            emu_cmd = DRV_IOD(DsProgrammingAclTcam0_t+emu_blk, DRV_ENTRY_FLAG);
            for (emu_idx=0; emu_idx<32; emu_idx++)
            {
                DRV_IOCTL(lchip, emu_idx, DRV_CMD_BMP_EN(emu_cmd, MCHIP_FEATURE_PP_EN(lchip,CTC_FEATURE_ACL)), &emu_cmd);
            }
        }
    }
    #endif
    SYS_CB_REGISTER(lchip, SYS_CB_ACL_SET_IFA_VER, sys_usw_acl_set_ifa_ver);

    sal_memset(&ftm_info, 0, sizeof(drv_ftm_info_detail_t));
    ftm_info.info_type = DRV_FTM_INFO_TYPE_MAX;
    CTC_ERROR_RETURN(drv_usw_ftm_get_info_detail(lchip, &ftm_info));
    if (ftm_info.nsh_mode)
    {
        CTC_ERROR_RETURN(sys_usw_acl_flow_hash_default_entry_init(lchip));
    }


    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_ACL);
    return CTC_E_NONE;

 ERROR_FREE_MEM:
    sys_usw_acl_deinit(lchip);
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Acl] Init failed \n");
    return CTC_E_INIT_FAIL;
}
int32
sys_usw_acl_init_done(uint8 lchip)
{
    uint8 dma_chan_en = 0;
    uint32 size = 0;
    if (NULL == p_usw_acl_master[lchip])
    {
        return CTC_E_NONE;
    }
    sys_usw_dma_get_chan_en(lchip, SYS_DMA_TBL_WR_CHAN_ID, &dma_chan_en);
    if(dma_chan_en && g_dal_op.dma_alloc)
    {
        size = DRV_FROM_AT(lchip) ? TABLE_ENTRY_OFFSET(lchip, ProgramIngAclTcamMem_t):TABLE_ENTRY_OFFSET(lchip, ProgramAclTcamMem_t);
        p_usw_acl_master[lchip]->replace_block_dma_buf = g_dal_op.dma_alloc(SYS_MAP_LDEV(lchip), SYS_USW_ACL_DMA_OP_SIZE*size, 0);
        if (NULL ==  p_usw_acl_master[lchip]->replace_block_dma_buf)
        {
            SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;
        }
    }
    return CTC_E_NONE;
}

/*
 * deinit acl module
 */
int32
sys_usw_acl_deinit(uint8 lchip)
{
    uint16       idx1 = 0;
    uint32      free_entry_hash = 1;

    LCHIP_CHECK(lchip);
    if (NULL == p_usw_acl_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT(lchip, p_usw_acl_master, CTC_FEATURE_ACL);

    sys_usw_ftm_register_callback(lchip, CTC_FTM_SPEC_ACL, NULL);
    sys_usw_ftm_register_callback(lchip, CTC_FTM_SPEC_ACL_FLOW, NULL);
    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_ACL,0, NULL);
    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_ACL, NULL);

    if(p_usw_acl_master[lchip]->replace_block_dma_buf && g_dal_op.dma_free)
    {
        SYS_DMA_FREE(lchip, p_usw_acl_master[lchip]->replace_block_dma_buf);
    }
    if(DRV_FROM_TMM(lchip) && p_usw_acl_master[lchip]->udf_fpa_en)
    {

        if(p_usw_acl_master[lchip]->udf_block.fpab.entries)
        {
            mem_free(p_usw_acl_master[lchip]->udf_block.fpab.entries);
        }
        fpa_usw_free(p_usw_acl_master[lchip]->udf_fpa);
    }
    /*ACL ingress and egress*/
    for (idx1 = 0; idx1 < ACL_IGS_BLOCK_MAX_NUM + ACL_EGS_BLOCK_MAX_NUM; idx1++)
    {
        if (SYS_ACL_BLOCK(lchip, idx1).fpab.vblock)
        {
            mem_free(SYS_ACL_BLOCK(lchip, idx1).fpab.vblock->entries);
            mem_free(SYS_ACL_BLOCK(lchip, idx1).fpab.vblock);
        }
        mem_free(SYS_ACL_BLOCK(lchip, idx1).fpab.entries);
        ctc_slist_free(SYS_ACL_BLOCK(lchip, idx1).group_list);
    }

    if(SYS_VCHIP_PP_IS_NOT_BASE(lchip))
    {
        p_usw_acl_master[lchip]->acl_mutex = NULL;
    }
    else
    {
        sal_mutex_destroy(p_usw_acl_master[lchip]->acl_mutex);
    }

    if (MCHIP_ACL(lchip)->deinit)
    {
        MCHIP_ACL(lchip)->deinit(lchip);
    }
    ctc_hash_free2(p_usw_acl_master[lchip]->ldp_hash, (hash_traversal_fn)sys_usw_free_ldp_node, NULL);
    /*free vlan edit data*/
    if (p_usw_acl_master[lchip]->vlan_edit_spool)
    {
        ctc_spool_free(p_usw_acl_master[lchip]->vlan_edit_spool);
    }

    /*free ad data*/
    if (p_usw_acl_master[lchip]->ad_spool)
    {
        ctc_spool_free(p_usw_acl_master[lchip]->ad_spool);
    }

    /*free cid data*/
    if (p_usw_acl_master[lchip]->cid_spool)
    {
        ctc_spool_free(p_usw_acl_master[lchip]->cid_spool);
    }

    /*free acl key*/
    ctc_hash_free2(p_usw_acl_master[lchip]->entry, (hash_traversal_fn)_sys_usw_acl_free_entry_node_data, &free_entry_hash);

    /*free acl group*/
    ctc_hash_free2(p_usw_acl_master[lchip]->group, (hash_traversal_fn)_sys_usw_acl_free_group_node_data, NULL);
    /*free udf entry */
    ctc_hash_free2(p_usw_acl_master[lchip]->udf_entry, (hash_traversal_fn)_sys_usw_acl_free_udf_entry_node_data, NULL);
    /*free fixed key*/
    ctc_vector_traverse(p_usw_acl_master[lchip]->fixed_key_vec, (vector_traversal_fn)_sys_usw_acl_free_vec_node_data, NULL);
    ctc_vector_release(p_usw_acl_master[lchip]->fixed_key_vec);
    /* free aset */
    if(!SYS_VCHIP_PP_IS_NOT_BASE(lchip))
    {
        ctc_vector_traverse(p_usw_acl_master[lchip]->aset_vec, (vector_traversal_fn)_sys_usw_acl_free_vec_node_data, NULL);
        ctc_vector_release(p_usw_acl_master[lchip]->aset_vec);
        mem_free(p_usw_acl_master[lchip]->support_aset);
        sys_usw_opf_deinit(lchip, p_usw_acl_master[lchip]->opf_type_aset);
    }
    /*free udf ad vector*/
    ctc_vector_traverse(p_usw_acl_master[lchip]->udf_ad, (vector_traversal_fn)_sys_usw_acl_free_vec_node_data, NULL);
    ctc_vector_release(p_usw_acl_master[lchip]->udf_ad);
    if (p_usw_acl_master[lchip]->kset_db[CTC_ACL_KEY_MAC])
    {
        mem_free(p_usw_acl_master[lchip]->kset_db[CTC_ACL_KEY_MAC]);
    }
    /*opf free*/
    if (p_usw_acl_master[lchip]->opf_type_ad)
    {
        sys_usw_opf_deinit(lchip, p_usw_acl_master[lchip]->opf_type_ad);
    }
    sys_usw_opf_deinit(lchip, p_usw_acl_master[lchip]->opf_type_vlan_edit);
    sys_usw_ofb_deinit(lchip, p_usw_acl_master[lchip]->ofb_type_cid,0);
    sys_usw_opf_deinit(lchip, p_usw_acl_master[lchip]->opf_type_cid_ad);
    sys_usw_opf_deinit(lchip, p_usw_acl_master[lchip]->opf_type_udf);

    SYS_CB_REGISTER(lchip, SYS_CB_ACL_SET_IFA_VER, NULL);

    fpa_usw_free(p_usw_acl_master[lchip]->fpa);
    //mem_free(p_usw_acl_master[lchip]->p_fixed_fg_user);
    //mem_free(p_usw_acl_master[lchip]->p_fixed_fg);
    mem_free(p_usw_acl_master[lchip]);


    return CTC_E_NONE;
}
int32
sys_usw_acl_map_l4_type_to_ip_protocol(uint8 lchip, uint8 l3_type, uint8 l4_type,
                                                   uint32* o_ip_protocol, uint32* o_mask)
{
    uint8 ip_protocol = 0;
    uint8 mask    = 0;

    switch(l4_type)
    {
        case CTC_PARSER_L4_TYPE_TCP:
            ip_protocol = SYS_L4_PROTOCOL_TCP;
            mask = 0xFF;
            break;
        case CTC_PARSER_L4_TYPE_UDP:
            ip_protocol = SYS_L4_PROTOCOL_UDP;
            mask = 0xFF;
            break;
        case CTC_PARSER_L4_TYPE_GRE:
            ip_protocol = SYS_L4_PROTOCOL_GRE;
            mask = 0xFF;
            break;
        case CTC_PARSER_L4_TYPE_IPINIP:
        case CTC_PARSER_L4_TYPE_IPINV6:
            ip_protocol = SYS_L4_PROTOCOL_IPV4;
            mask = 0xFF;
            break;
        case CTC_PARSER_L4_TYPE_V6INIP:
        case CTC_PARSER_L4_TYPE_V6INV6:
            ip_protocol = SYS_L4_PROTOCOL_IPV6;
            mask = 0xFF;
            break;
        case CTC_PARSER_L4_TYPE_ICMP:
            if(CTC_PARSER_L3_TYPE_IPV4 == l3_type)
            {
                ip_protocol = SYS_L4_PROTOCOL_IPV4_ICMP;
                mask = 0xFF;
            }
#if 0
            else if(CTC_PARSER_L3_TYPE_IPV6 == l3_type)
            {
                ip_protocol = SYS_L4_PROTOCOL_IPV6_ICMP;
                mask = 0xFF;
            }
#endif
            break;
        case CTC_PARSER_L4_TYPE_IGMP:
            ip_protocol = SYS_L4_PROTOCOL_IPV4_IGMP;
            mask = 0xFF;
            break;
        case CTC_PARSER_L4_TYPE_RDP:
            ip_protocol = SYS_L4_PROTOCOL_RDP;
            mask = 0xFF;
            break;
        case CTC_PARSER_L4_TYPE_SCTP:
            ip_protocol = SYS_L4_PROTOCOL_SCTP;
            mask = 0xFF;
            break;
        case CTC_PARSER_L4_TYPE_DCCP:
            ip_protocol = SYS_L4_PROTOCOL_DCCP;
            mask = 0xFF;
            break;
        /*CTC_PARSER_L4_TYPE_PBB_ITAG_OAM ; CTC_PARSER_L4_TYPE_ACH_OAM not support */
        default:
            return CTC_E_NOT_SUPPORT;
    }

    if(o_ip_protocol)
    {
        *o_ip_protocol = ip_protocol;
    }

    if(o_mask)
    {
        *o_mask = mask;
    }
    return CTC_E_NONE;
}

int32
sys_usw_acl_map_ip_protocol_to_l4_type(uint8 lchip, uint8 l3_type, uint8 ip_protocol,
                                                   uint32* o_l4_type, uint32* o_mask)
{
    uint8 l4_type = CTC_PARSER_L4_TYPE_NONE;
    uint8 mask    = 0;

    switch(ip_protocol)
    {
        case SYS_L4_PROTOCOL_TCP:
            l4_type = CTC_PARSER_L4_TYPE_TCP;
            mask = 0xF;
            break;
        case SYS_L4_PROTOCOL_UDP:
            l4_type = CTC_PARSER_L4_TYPE_UDP;
            mask = 0xF;
            break;
        case SYS_L4_PROTOCOL_GRE:
            l4_type = CTC_PARSER_L4_TYPE_GRE;
            mask = 0xF;
            break;
        case SYS_L4_PROTOCOL_IPV4:
            if(CTC_PARSER_L3_TYPE_IPV4 == l3_type)
            {
                l4_type = CTC_PARSER_L4_TYPE_IPINIP;
                mask = 0xF;
            }
            else if(CTC_PARSER_L3_TYPE_IPV6 == l3_type)
            {
                l4_type = CTC_PARSER_L4_TYPE_IPINV6;
                mask = 0xF;
            }
            break;
        case SYS_L4_PROTOCOL_IPV6:
            if(CTC_PARSER_L3_TYPE_IPV4 == l3_type)
            {
                l4_type = CTC_PARSER_L4_TYPE_V6INIP;
                mask = 0xF;
            }
            else if(CTC_PARSER_L3_TYPE_IPV6 == l3_type)
            {
                l4_type = CTC_PARSER_L4_TYPE_V6INV6;
                mask = 0xF;
            }
            break;
        case SYS_L4_PROTOCOL_IPV4_ICMP:
        case SYS_L4_PROTOCOL_IPV6_ICMP:
            l4_type = CTC_PARSER_L4_TYPE_ICMP;
            mask = 0xF;
            break;
        case SYS_L4_PROTOCOL_IPV4_IGMP:
            l4_type = CTC_PARSER_L4_TYPE_IGMP;
            mask = 0xF;
            break;
        case SYS_L4_PROTOCOL_RDP:
            l4_type = CTC_PARSER_L4_TYPE_RDP;
            mask = 0xF;
            break;
        case SYS_L4_PROTOCOL_SCTP:
            l4_type = CTC_PARSER_L4_TYPE_SCTP;
            mask = 0xF;
            break;
        case SYS_L4_PROTOCOL_DCCP:
            l4_type = CTC_PARSER_L4_TYPE_DCCP;
            mask = 0xF;
            break;

        default:
            break;      /*mustn't return, for some key support l4 type*/
    }

    if(o_l4_type)
    {
        *o_l4_type = l4_type;
    }

    if(o_mask)
    {
        *o_mask = mask;
    }
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "ip protocol map to l4 type:%u, mask:%X\n", l4_type, mask);
    return CTC_E_NONE;
}

char*
sys_usw_acl_output_udf(uint8* in_data)
{
    static char out_data[40] = {0};
    uint8 i = 0;
    for(i = 0; i<SYS_ACL_UDF_HALF_FIELD_NUM; i++)
    {
        sal_sprintf(&out_data[i*2], "%02X", in_data[i]);
    }
    return out_data;
}

int32
sys_usw_acl_lookup_entry_hash(uint8 lchip, uint32 entry_id, uint8 type, uint16* pp_bmp)
{
    sys_com_entry_hash_t* p_node = NULL;

    if(!p_usw_acl_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_USW_ACL_LOCK(lchip);
    p_node = sys_usw_com_lookup_entry_hash(lchip, p_usw_acl_master[lchip]->entry_hash_db[type], entry_id);
    if(p_node == NULL)
    {
        SYS_USW_ACL_UNLOCK(lchip);
        return CTC_E_NOT_EXIST;
    }
    else
    {
        *pp_bmp = p_node->pp_bmp;
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_acl_add_entry_hash(uint8 lchip, uint32 entry_id, uint16 pp_bmp, uint8 type)
{
    int32 ret = CTC_E_NONE;

    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_USW_ACL_LOCK(lchip);
    ret = sys_usw_com_add_entry_hash(lchip, MEM_ACL_MODULE, p_usw_acl_master[lchip]->entry_hash_db[type], entry_id, pp_bmp);
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}

int32
sys_usw_acl_remove_entry_hash(uint8 lchip, uint32 entry_id, uint8 type)
{
    int32 ret = CTC_E_NONE;
    sys_com_entry_hash_t* p_node = NULL;

    SYS_ACL_INIT_CHECK();
    SYS_ACL_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_USW_ACL_LOCK(lchip);
    p_node = sys_usw_com_lookup_entry_hash(lchip, p_usw_acl_master[lchip]->entry_hash_db[type], entry_id);
    if(p_node == NULL)
    {
        ret = CTC_E_NOT_EXIST;
    }
    else
    {
        ret = sys_usw_com_remove_entry_hash(lchip, p_usw_acl_master[lchip]->entry_hash_db[type], p_node);
    }
    SYS_USW_ACL_UNLOCK(lchip);
    return ret;
}



#define __ACL_RESOLVE_ROUTE_
#define SYS_IPUC_ACL_BLOCK_NUM 129

